CF1290E Cartesian Tree
作者:互联网
CF1290E Cartesian Tree
题意
\(~~~~\) 给定一个 \(1 \sim n\) 的排列,对于一个整数 \(k\in[1,n]\) ,定义其权值 \(s_k\) 为将排列中 \(\leq k\) 的项的子序列构成大根笛卡尔树后所有节点的子树大小和。\(\forall i\in[1,n]\) 求 \(s_i\).
\(~~~~\) \(1\leq n\leq 1.5\times 10^5\).
题解
\(~~~~\) 作为数据结构确实比较精妙,但实现略恶心。
\(~~~~\) 首先我们发现加入一个新的数后笛卡尔树就很可能会大变样,所以我们不太可能直接维护笛卡尔树。
\(~~~~\) 「你是你 或是妳 都行/会有人 全心的 爱你」既然你不太能上树那就直接放到序列上思考。
\(~~~~\) 关于笛卡尔树的子树大小,我们不难想到就是其所作为最值的最大区间大小,这里由于是大根笛卡尔树所以就是最大的作为最大值的区间大小。所以我们需要维护 \(\sum(r_i-l_i+1)\) ,则对于第 \(i\) 个数加入后,答案为 \(\sum r_i-\sum l_i +k\) 。当然我们也可以维护前后第一个比它大的数的位置,那就是 \(\sum r_i-\sum l_i-k\) 。这里笔者采用了后者。
\(~~~~\) 所以我们来考虑从小到大加入时,加入一个数会有何变化。假设加入的数 \(x\) 在现在的序列中为第 \(p\) 个(这可以用树状数组简单求出),则:
-
对于在它前面的数,其 \(r\) 会变为 \(\min(r,p)\)
-
对于在它后面的数,有 \(l\leftarrow l+1,r\leftarrow r+1\),之后其 \(l\) 会变为 \(\max(l,p)\).
-
对于它本身,其 \(l\) 会变为 \(0\) ,\(r\) 会变为 \(x+1\).
\(~~~~\) 那综上,我们要做的就是:维护区间取最值,区间加法,单点赋值。直接上吉司机线段树(Segment Beats) 就行了。
\(~~~~\) 但是需要注意的是,我们每次维护的 \(l,r\) 都是在当前序列的意义下的,所以维护和时只能维护存在于当前序列的位置的和。当然这很好解决,打一个 \(Len\) 标记表示可用的位置数即可。至于写两种标记还是数域划分就看个人喜好了。
\(~~~~\) 此外为了防止同时写两种最值操作,不妨把 \(l\) 相关的部分取反维护,这样可以少写一棵线段树。
代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int INF=1e9;
struct SegmnetTree{
#define ls p<<1
#define rs p<<1|1
#define lson p<<1,l,mid
#define rson p<<1|1,mid+1,r
ll Tag1[600005],Tag2[600005];
ll Maxn[600005],Maxn2[600005],Cnt[600005],Sum[600005],Len[600005];
void pushUp(int p)
{
Len[p]=Len[ls]+Len[rs]; Maxn[p]=max(Maxn[ls],Maxn[rs]); Sum[p]=Sum[ls]+Sum[rs];
if(Maxn[ls]==Maxn[rs]) Maxn2[p]=max(Maxn2[ls],Maxn2[rs]),Cnt[p]=Cnt[ls]+Cnt[rs];
if(Maxn[ls]>Maxn[rs]) Maxn2[p]=max(Maxn2[ls],Maxn[rs]),Cnt[p]=Cnt[ls];
if(Maxn[ls]<Maxn[rs]) Maxn2[p]=max(Maxn[ls],Maxn2[rs]),Cnt[p]=Cnt[rs];
}
void Add(int p,int T1,int T2)
{
if(Maxn2[p]==-INF) Maxn[p]+=T1,Sum[p]+=Len[p]*T1;
else Maxn[p]+=T1,Maxn2[p]+=T2,Sum[p]+=Cnt[p]*T1+(Len[p]-Cnt[p])*T2;
Tag1[p]+=T1; Tag2[p]+=T2;
}
void pushDown(int p)
{
int Max=max(Maxn[ls],Maxn[rs]);
Add(ls,Maxn[ls]==Max?Tag1[p]:Tag2[p],Tag2[p]);
Add(rs,Maxn[rs]==Max?Tag1[p]:Tag2[p],Tag2[p]);
Tag1[p]=Tag2[p]=0;
}
void Build(int p,int l,int r)
{
if(l==r)
{
Maxn[p]=Maxn2[p]=-INF; Cnt[p]=Len[p]=Sum[p]=0;
return;
}
int mid=(l+r)>>1;
Build(lson); Build(rson);
pushUp(p);
}
void Modify(int p,int l,int r,int lx,int rx,int val,int op)
{
if(l>r||lx>rx) return;
if(!Len[p]) return;
if(op==1&&lx<=l&&r<=rx) {Add(p,val,val);return;}
if(op==2&&Maxn[p]<=val) return;
if(op==2&&lx<=l&&r<=rx&&Maxn2[p]<val) {Add(p,val-Maxn[p],0);return;}
int mid=(l+r)>>1; pushDown(p);
if(lx<=mid) Modify(lson,lx,rx,val,op);
if(mid<rx) Modify(rson,lx,rx,val,op);
pushUp(p);
}
void Give(int p,int l,int r,int aim,int val)
{
if(l==r) {Maxn[p]=Sum[p]=val,Maxn2[p]=-INF,Cnt[p]=Len[p]=1;return;}
int mid=(l+r)>>1; pushDown(p);
if(aim<=mid) Give(lson,aim,val);
if(mid<aim) Give(rson,aim,val);
pushUp(p);
}
ll Query(){return Sum[1];}
ll DEBUG(int p,int l,int r,int aim)
{
if(l==r) return Sum[p];
int mid=(l+r)>>1;pushDown(p);
if(aim<=mid) return DEBUG(lson,aim);
if(mid<aim) return DEBUG(rson,aim);
}
#undef ls
#undef rs
#undef lson
#undef rson
}Seg1,Seg2;
template<typename T>void read(T &x)
{
T f=1;x=0;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9') {x=x*10+s-'0';s=getchar();}
x*=f;
}
int n,pos[150005],pos2[150005],Del;
struct BIT{
int tr[150005];
inline int lowbit(int x){return x&(-x);}
void Add(int x,int val){for(;x<=n;x+=lowbit(x)) tr[x]+=val;}
int Query(int x){int ret=0;for(;x;x-=lowbit(x)) ret+=tr[x];return ret;}
}BIT;
int main() {
read(n);
for(int i=1,x;i<=n;i++) read(x),pos[x]=i,pos2[x]=BIT.Query(x)+1,BIT.Add(x,1);//pos2 表示最开始插入在第几个
Seg1.Build(1,1,n); Seg2.Build(1,1,n);
for(int i=1;i<=n;i++)
{
Seg1.Give(1,1,n,pos[i],0); Seg2.Give(1,1,n,pos[i],i+1);
Seg1.Modify(1,1,n,pos[i]+1,n,-1,1); Seg2.Modify(1,1,n,pos[i]+1,n,1,1);
Seg1.Modify(1,1,n,pos[i]+1,n,-pos2[i],2); Seg2.Modify(1,1,n,1,pos[i]-1,pos2[i],2);
printf("%lld\n",Seg2.Query()+Seg1.Query()-i);
// for(int j=1;j<=n;j++) printf("(%d %d)",-Seg1.DEBUG(1,1,n,j),Seg2.DEBUG(1,1,n,j));puts("");
}
return 0;
}
标签:Cartesian,笛卡尔,int,sum,Tree,CF1290E,ls,维护,lx 来源: https://www.cnblogs.com/Azazel/p/16464088.html