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
    */
    
    
  • 相关阅读:
    IIS与ASP.NET中的线程池
    IIS与ASP.NET中的队列
    让ASP.NET OutputCache使用http.sys kernel-mode cache
    微软的坑:Url重写竟然会引起IIS内核模式缓存不工作
    实际案例:在现有代码中通过async/await实现并行
    困扰多日的C#调用Haskell问题竟然是Windows的一个坑
    C#调用haskell遭遇Attempted to read or write protected memory
    经过实际验证的C#调用Haskell的方法
    Haskell中cabal install glib遇到的问题
    Haskell ghci中调用pandoc的API进行markdown转换
  • 原文地址:https://www.cnblogs.com/Purple-wzy/p/13308506.html
Copyright © 2011-2022 走看看