CF1290E Cartesian Tree

时间:2020-07-15
本文章向大家介绍CF1290E Cartesian Tree,主要包括CF1290E Cartesian Tree使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

题面

英文题面

题意:

笛卡尔树是一种既满足堆的性质,又满足二叉搜索树的性质的树。可以发现的是,对于一个排列,它的笛卡尔树是唯一的。

\(n \leq 2\times 10^5\)

题解:发现笛卡尔树中的一个节点的权值可以表示为\(r_i-l_i+1\)的形式。其中\(r_i\)表示最小的\(p \geq i\),使得\(a_{p+1}>a_i\)。所以我们可以分别维护\(l_i\)\(r_i\)

考虑加入一个权值最大的点后,\(r_i\)\(l_i\)会出现哪些变化。设当前插入的是数字\(i\),它在排列中的位置是\(p\),它在当前的由1到\(i\)组成的子序列中的位置为\(q\)

  • 对于\(\forall_{k<p}\)\(r_k=min(r_k,q-1)\)
  • 对于\(p\)\(l_p=1,r_p=i\)
  • 对于\(\forall_{k>p},l_k++,r_k++,l_k=max(l_k,q+1)\)

所以相当于是区间取min,区间加和单点赋值。我们可以采用势能线段树的思想,维护:

  • 区间和;
  • 最大(小)值;
  • 最大(小)值出现次数;
  • 次大(小)值;
  • 区间合法点个数;
  • 加法标记和赋值标记。

对于区间取min操作,我们递归到一个区间,其最大值小于\(w\),次大值大于等于\(w\)时进行修改,否则继续递归子树。

不会势能线段树区间取min复杂度证明的可以出门右转自行百度。

注意pushup和pushdown各要分三种情况讨论,还要注意标记的下传顺序问题。

时间复杂度:\(O(nlog^2n)\)

代码:

#include<bits/stdc++.h>
using namespace std;
#define re register int
#define F(x,y,z) for(re x=y;x<=z;x++)
#define FOR(x,y,z) for(re x=y;x>=z;x--)
typedef long long ll;
#define I inline void
#define IN inline int
#define C(x,y) memset(x,y,sizeof(x))
#define STS system("pause")
template<class D>I read(D &res){
	res=0;register D g=1;register char ch=getchar();
	while(!isdigit(ch)){
		if(ch=='-')g=-1;
		ch=getchar();
	}
	while(isdigit(ch)){
		res=(res<<3)+(res<<1)+(ch^48);
		ch=getchar();
	}
	res*=g;
}
const int INF=1e9+7;
int n,m,a[202000],p[202000],t[202000];
IN lbt(int x){return x&(-x);}
I modi(int x,int w){while(x<=n)t[x]+=w,x+=lbt(x);}
IN ques(int x){re res=0;while(x)res+=t[x],x-=lbt(x);return res;}
#define all 1,1,n
#define lt k<<1,l,mid
#define rt k<<1|1,mid+1,r
ll sr[1606000],sl[1606000];int cntr[1606000],cntl[1606000];
int mxr[1606000],mxl[1606000],smxr[1606000],smxl[1606000],cmxr[1606000],cmxl[1606000],snl[1606000],snr[1606000];
int lazr[1606000],lazl[1606000],lmr[1606000],lml[1606000];
I build(int k,int l,int r){
	sl[k]=sr[k]=cntr[k]=cntl[k]=cmxr[k]=cmxl[k]=lazr[k]=lazl[k]=lmr[k]=lml[k]=0;
	mxr[k]=smxr[k]=-INF;mxl[k]=smxl[k]=INF;
	if(l==r)return;
	re mid=(l+r)>>1;
	build(lt);build(rt);
}
I push_upl(int k){
	sl[k]=sl[k<<1]+sl[k<<1|1];cntl[k]=cntl[k<<1]+cntl[k<<1|1];
	if(mxl[k<<1]<mxl[k<<1|1]){
		snl[k]=1;
		mxl[k]=mxl[k<<1];cmxl[k]=cmxl[k<<1];smxl[k]=min(smxl[k<<1],mxl[k<<1|1]);
	}
	else if(mxl[k<<1]>mxl[k<<1|1]){
		snl[k]=2;
		mxl[k]=mxl[k<<1|1];cmxl[k]=cmxl[k<<1|1];smxl[k]=min(smxl[k<<1|1],mxl[k<<1]);
	}
	else{
		snl[k]=3;
		mxl[k]=mxl[k<<1];cmxl[k]=cmxl[k<<1]+cmxl[k<<1|1];smxl[k]=min(smxl[k<<1],smxl[k<<1|1]);
	}
}
I push_upr(int k){
	sr[k]=sr[k<<1]+sr[k<<1|1];cntr[k]=cntr[k<<1]+cntr[k<<1|1];
	if(mxr[k<<1]>mxr[k<<1|1]){
		snr[k]=1;
		mxr[k]=mxr[k<<1];cmxr[k]=cmxr[k<<1];smxr[k]=max(smxr[k<<1],mxr[k<<1|1]);
	}
	else if(mxr[k<<1]<mxr[k<<1|1]){
		snr[k]=2;
		mxr[k]=mxr[k<<1|1];cmxr[k]=cmxr[k<<1|1];smxr[k]=max(smxr[k<<1|1],mxr[k<<1]);
	}
	else{
		snr[k]=3;
		mxr[k]=mxr[k<<1];cmxr[k]=cmxr[k<<1]+cmxr[k<<1|1];smxr[k]=max(smxr[k<<1],smxr[k<<1|1]);
	}
}
I add_l(int k,int w){
	sl[k]+=(ll)cntl[k]*w;if(mxl[k]!=INF)mxl[k]+=w;if(smxl[k]!=INF)smxl[k]+=w;lazl[k]+=w;
}
I maxl(int k,int w){
	if(lazl[k]){
		add_l(k<<1,lazl[k]);add_l(k<<1|1,lazl[k]);lazl[k]=0;
	}
	sl[k]+=(ll)cmxl[k]*(w-mxl[k]);mxl[k]=cmxl[k]?w:INF;lml[k]=w;
}
I push_downl(int k){
	if(lml[k]){
		if(snl[k]^2)maxl(k<<1,lml[k]);
		if(snl[k]^1)maxl(k<<1|1,lml[k]);
		lml[k]=0;
	}
	if(lazl[k]){
		add_l(k<<1,lazl[k]);add_l(k<<1|1,lazl[k]);lazl[k]=0;
	}
}
I add_r(int k,int w){
	sr[k]+=(ll)cntr[k]*w;if(mxr[k]!=-INF)mxr[k]+=w;if(smxr[k]!=-INF)smxr[k]+=w;lazr[k]+=w;
}
I minr(int k,int w){
	if(lazr[k]){
		add_r(k<<1,lazr[k]);add_r(k<<1|1,lazr[k]);lazr[k]=0;
	}
	sr[k]+=(ll)cmxr[k]*(w-mxr[k]);mxr[k]=cmxr[k]?w:-INF;lmr[k]=w;
}
I push_downr(int k){
	if(lmr[k]){
		if(snr[k]^2)minr(k<<1,lmr[k]);
		if(snr[k]^1)minr(k<<1|1,lmr[k]);
		lmr[k]=0;
	}
	if(lazr[k]){
		add_r(k<<1,lazr[k]);add_r(k<<1|1,lazr[k]);lazr[k]=0;
	}
}
I modi_l(int k,int l,int r,int x,int w){
	if(l==r){
		sl[k]=mxl[k]=w;smxl[k]=INF;cmxl[k]=cntl[k]=1;
		return;
	}
	push_downl(k);
	re mid=(l+r)>>1;
	if(x<=mid)modi_l(lt,x,w);
	else modi_l(rt,x,w);
	push_upl(k);
}
I modi_r(int k,int l,int r,int x,int w){
	if(l==r){
		sr[k]=mxr[k]=w;smxr[k]=-INF;cmxr[k]=cntr[k]=1;
		return;
	}
	push_downr(k);
	re mid=(l+r)>>1;
	if(x<=mid)modi_r(lt,x,w);
	else modi_r(rt,x,w);
	push_upr(k);
}
I revi_l(int k,int l,int r,int x,int y,int w){
	if(x>r||y<l||!cntl[k])return;
	if(x<=l&&r<=y)return add_l(k,w),void();
	push_downl(k);
	re mid=(l+r)>>1;
	revi_l(lt,x,y,w);revi_l(rt,x,y,w);
	push_upl(k);
}
I revi_r(int k,int l,int r,int x,int y,int w){
	if(x>r||y<l||!cntr[k])return;
	if(x<=l&&r<=y)return add_r(k,w),void();
	push_downr(k);
	re mid=(l+r)>>1;
	revi_r(lt,x,y,w);revi_r(rt,x,y,w);
	push_upr(k);
}
I fill_max(int k,int l,int r,int x,int y,int w){
	if(x>r||y<l||!cntl[k]||mxl[k]>=w)return;
	if(x<=l&&r<=y){
		if(smxl[k]>=w){
//			cout<<"#"<<l<<" "<<r<<" "<<w<<endl;
			return maxl(k,w),void();
		}
		push_downl(k);
		re mid=(l+r)>>1;
		fill_max(lt,x,y,w);fill_max(rt,x,y,w);
		return push_upl(k),void();
	}
	push_downl(k);
	re mid=(l+r)>>1;
	fill_max(lt,x,y,w);fill_max(rt,x,y,w);
	push_upl(k);
}
I fill_min(int k,int l,int r,int x,int y,int w){
	if(x>r||y<l||!cntr[k]||mxr[k]<=w)return;
	if(x<=l&&r<=y){
		if(smxr[k]<=w){
//			cout<<"@"<<l<<" "<<r<<" "<<w<<endl;
			return minr(k,w),void();
		}
		push_downr(k);
		re mid=(l+r)>>1;
		fill_min(lt,x,y,w);fill_min(rt,x,y,w);
		return push_upr(k),void();
	}
	push_downr(k);
	re mid=(l+r)>>1;
	fill_min(lt,x,y,w);fill_min(rt,x,y,w);
	push_upr(k);
}
I getit(int k,int l,int r){
	cout<<"!"<<k<<" "<<l<<" "<<r<<" "<<sl[k]<<" "<<sr[k]<<" "<<mxl[k]<<" "<<mxr[k]<<" "<<smxl[k]<<" "<<smxr[k]<<" "<<cmxl[k]<<" "<<cmxr[k]<<endl;
	if(l==r)return ;//cout<<k<<" "<<l<<" "<<r<<" "<<sl[k]<<" "<<sr[k]<<endl,void();
	push_downl(k);push_downr(k);
	re mid=(l+r)>>1;
	getit(lt);getit(rt);
}
int main(){
//	freopen("a.out","w",stdout);
	read(n);F(i,1,n)read(a[i]),p[a[i]]=i;build(all);
	F(i,1,n){
		modi_l(all,p[i],1),modi_r(all,p[i],i);
		m=ques(p[i])+1;modi(p[i],1);revi_l(all,p[i]+1,n,1);revi_r(all,p[i]+1,n,1);
		fill_max(all,p[i]+1,n,m+1);fill_min(all,1,p[i]-1,m-1);
		printf("%lld\n",sr[1]-sl[1]+i);
//		getit(all);
	}
	return 0;
}
/*
5
2 4 1 5 3
6
1 2 4 5 6 3
10
8 10 9 3 7 5 4 6 2 1
15
1 7 12 14 15 9 8 10 11 2 5 4 3 13 6
*/

原文地址:https://www.cnblogs.com/Purple-wzy/p/13308506.html