zoukankan      html  css  js  c++  java
  • CF1290E Cartesian Tree

    题面

    英文题面

    题意:

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

    (n leq 2 imes 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
    ",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
    */
    
    
  • 相关阅读:
    vue开发chrome扩展,数据通过storage对象获取
    Vue手动集成less预编译器
    Google Translate寻找之旅
    Javascript Range对象的学习
    Javascript Promises学习
    SublimeText 建立构建Node js系统
    We're sorry but demo3 doesn't work properly without JavaScript enabled. Please enable it to continue.
    npm安装包出现UNMET DEPENDENCY报错
    (转载)命令行说明中格式 尖括号 中括号的含义
    Linux重启网卡服务Failed to start LSB: Bring up/down networking.
  • 原文地址:https://www.cnblogs.com/Purple-wzy/p/13308506.html
Copyright © 2011-2022 走看看