題面c++
英文題面git
題意:ui
笛卡爾樹是一種既知足堆的性質,又知足二叉搜索樹的性質的樹。能夠發現的是,對於一個排列,它的笛卡爾樹是惟一的。spa
\(n \leq 2\times 10^5\)。code
題解:發現笛卡爾樹中的一個節點的權值能夠表示爲\(r_i-l_i+1\)的形式。其中\(r_i\)表示最小的\(p \geq i\),使得\(a_{p+1}>a_i\)。因此咱們能夠分別維護\(l_i\)和\(r_i\)。blog
考慮加入一個權值最大的點後,\(r_i\)和\(l_i\)會出現哪些變化。設當前插入的是數字\(i\),它在排列中的位置是\(p\),它在當前的由1到\(i\)組成的子序列中的位置爲\(q\)。遞歸
因此至關因而區間取min,區間加和單點賦值。咱們能夠採用勢能線段樹的思想,維護:get
對於區間取min操做,咱們遞歸到一個區間,其最大值小於\(w\),次大值大於等於\(w\)時進行修改,不然繼續遞歸子樹。it
不會勢能線段樹區間取min複雜度證實的能夠出門右轉自行百度。class
注意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 */