题意:
笛卡尔树是一种既满足堆的性质,又满足二叉搜索树的性质的树。可以发现的是,对于一个排列,它的笛卡尔树是唯一的。
(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
*/