ETT的模板题。
我们把欧拉序标出来, 把入栈视作+,出栈视作-。
它的子树一定是在两个欧拉序中间的。
然后把欧拉序当做一个区间维护,换父亲就把左右两端这个区间挪到它的新父亲的入栈的右边。用splay维护一下就行了。
但是!这个@#$%^&题卡数组版splay?????
但是不卡spaly???(单旋splay)
??????
/************************************************************** Problem: 3786 User: 568877201 Language: C++ Result: Accepted Time:26980 ms Memory:17020 kb ****************************************************************/ #include <iostream> #include <cstdio> using namespace std; const int N=200005; struct Splay { int ch[2],fa,ld,rd,ty; long long tag,sum,val; } t[N]; int rnk[N],dfn1[N],dfn2[N],tim,rt,nxt[N],to[N],ecnt,head[N],a[N]; inline int read() { char c=getchar(); int x=0,f=1; while(c<'0'||c>'9') { if(c=='-')f=-1; c=getchar(); } while(c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar(); } return x*f; } inline void pushup(int x) { t[x].ld=t[t[x].ch[0]].ld+t[t[x].ch[1]].ld+(t[x].ty==1); t[x].rd=t[t[x].ch[0]].rd+t[t[x].ch[1]].rd+(t[x].ty==-1); t[x].sum=t[t[x].ch[0]].sum+t[t[x].ch[1]].sum+(t[x].val); } inline void add(int bg,int ed) { nxt[++ecnt]=head[bg]; to[ecnt]=ed; head[bg]=ecnt; } inline void doit(int x,int v) { t[x].val+=1ll*v*t[x].ty; t[x].sum+=1ll*v*(t[x].ld-t[x].rd); t[x].tag+=1ll*v; } inline void pushdown(int x) { if(t[x].tag) { if(t[x].ch[0]) doit(t[x].ch[0],t[x].tag); if(t[x].ch[1]) doit(t[x].ch[1],t[x].tag); t[x].tag=0; } } inline void rotate(int x) { int f=t[x].fa,ff=t[f].fa; bool tag=x==t[t[x].fa].ch[1]; t[f].ch[tag]=t[x].ch[tag^1]; t[t[f].ch[tag]].fa=f; t[x].ch[tag^1]=f; t[f].fa=x; t[x].fa=ff; if(ff) t[ff].ch[f==t[ff].ch[1]]=x; pushup(f); pushup(x); } void PUSHDOWN(int x) { if(t[x].fa) PUSHDOWN(t[x].fa); pushdown(x); } inline void splay(int x,int tar) { PUSHDOWN(x); for(int f; (f=t[x].fa)!=tar; rotate(x)) if(t[f].fa!=tar) rotate((x==t[t[x].fa].ch[1])==(f==t[t[f].fa].ch[1])?f:x); if(!tar) rt=x; } int build(int l,int r,int f) { int mid=l+r>>1,x=mid; t[x].fa=f; if(rnk[x]>0) t[x].val=a[rnk[x]],t[x].ty=1; else t[x].val=-a[-rnk[x]],t[x].ty=-1; if(l<mid)t[x].ch[0]=build(l,mid-1,x); if(mid<r)t[x].ch[1]=build(mid+1,r,x); pushup(x); return x; } inline int Nxt() { int x=t[rt].ch[1]; while(t[x].ch[0]) x=t[x].ch[0]; return x; } inline int pre() { int x=t[rt].ch[0]; while(t[x].ch[1]) x=t[x].ch[1]; return x; } inline void split(int &x,int &y) { splay(x,0); x=pre(); splay(y,0); y=Nxt(); splay(x,0); splay(y,x); } inline void query(int x) { int a=dfn1[1],b=dfn1[x]; split(a,b); printf("%lld ",t[t[b].ch[0]].sum); } inline void change(int x,int f) { int a=dfn1[x],b=dfn2[x]; split(a,b); int c=t[b].ch[0]; t[b].ch[0]=t[c].fa=0; pushup(b),pushup(a); a=dfn1[f]; splay(a,0); b=Nxt(); splay(b,a); t[b].ch[0]=c; t[c].fa=b; pushup(b),pushup(a); } inline void addv(int x,int v) { int a=dfn1[x],b=dfn2[x]; split(a,b); doit(t[b].ch[0],v); } void dfs(int x) { dfn1[x]=++tim; rnk[tim]=x; for(int i=head[x]; i; i=nxt[i]) dfs(to[i]); dfn2[x]=++tim; rnk[tim]=-x; } int n; signed main() { n=read(); for(int i=2; i<=n; i++) add(read(),i); for(int i=1; i<=n; i++) a[i]=read(); tim=1; dfs(1); tim++; rt=build(1,tim,0); int m; m=read(); char opt[10]; int x,y,z; while(m--) { scanf("%s",opt); switch (opt[0]) { case 'Q': query(read()); break; case 'C': x=read(),change(x,read()); break; case 'F': x=read(),addv(x,read()); break; } } }
如果哪位dalao看出我的数组版哪里有锅,感激不尽。。。
/************************************************************** Problem: 3786 User: 568877201 Language: C++ Result: Time_Limit_Exceed ****************************************************************/ #include <iostream> #include <cstdio> using namespace std; const int N=200005; int ch[N][2],fa[N],ld[N],rd[N],rnk[N],dfn1[N],dfn2[N],tim,ty[N],rt,nxt[N],to[N],ecnt,head[N],a[N]; long long tag[N],sum[N],val[N]; inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();} return x*f; } inline void pushup(int x){ ld[x]=ld[ch[x][0]]+ld[ch[x][1]]+(ty[x]==1); rd[x]=rd[ch[x][0]]+rd[ch[x][1]]+(ty[x]==-1); sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+val[x]; } //czqak// inline void add(int bg,int ed) {nxt[++ecnt]=head[bg];to[ecnt]=ed;head[bg]=ecnt;} inline void doit(int x,int v) { val[x]+=1ll*v*ty[x]; sum[x]+=1ll*v*(ld[x]-rd[x]); tag[x]+=1ll*v; } inline void pushdown(int x) { if(tag[x]) { if(ch[x][0]) doit(ch[x][0],tag[x]); if(ch[x][1]) doit(ch[x][1],tag[x]); tag[x]=0; } } inline void rotate(int x) { int f=fa[x],ff=fa[f]; bool tag=x==ch[fa[x]][1]; ch[f][tag]=ch[x][tag^1]; fa[ch[f][tag]]=f; ch[x][tag^1]=f; fa[f]=x; fa[x]=ff; if(ff) ch[ff][f==ch[ff][1]]=x; pushup(f);pushup(x); } void PUSHDOWN(int x) {if(fa[x]) PUSHDOWN(fa[x]);pushdown(x);} inline void splay(int x,int tar) { PUSHDOWN(x); for(int f;(f=fa[x])!=tar;rotate(x)) if(fa[f]!=tar) rotate((x==ch[fa[x]][1])==(f==ch[fa[f]][1])?f:x); if(!tar) rt=x; } int build(int l,int r,int f) { int mid=l+r>>1,x=mid; fa[x]=f; if(rnk[x]>0) val[x]=a[rnk[x]],ty[x]=1;else val[x]=-a[-rnk[x]],ty[x]=-1; if(l<mid)ch[x][0]=build(l,mid-1,x); if(mid<r)ch[x][1]=build(mid+1,r,x); pushup(x); return x; } inline int Nxt(){ int x=ch[rt][1]; while(ch[x][0]) x=ch[x][0]; return x; } inline int pre() { int x=ch[rt][0]; while(ch[x][1]) x=ch[x][1]; return x; } inline void split(int &x,int &y) { splay(x,0);x=pre(); splay(y,0);y=Nxt(); splay(x,0);splay(y,x); } inline void query(int x) { int a=dfn1[1],b=dfn1[x]; split(a,b); printf("%lld ",sum[ch[b][0]]); } inline void change(int x,int f) { int a=dfn1[x],b=dfn2[x]; split(a,b); int c=ch[b][0]; ch[b][0]=fa[c]=0; pushup(b),pushup(a); a=dfn1[f];splay(a,0); b=Nxt();splay(b,a); ch[b][0]=c;fa[c]=b; pushup(b),pushup(a); } inline void addv(int x,int v) { int a=dfn1[x],b=dfn2[x]; split(a,b); doit(ch[b][0],v); } void dfs(int x) { dfn1[x]=++tim;rnk[tim]=x; for(int i=head[x];i;i=nxt[i]) dfs(to[i]); dfn2[x]=++tim;rnk[tim]=-x; } int n; signed main() { n=read(); for(int i=2;i<=n;i++) add(read(),i); for(int i=1;i<=n;i++) a[i]=read(); tim=1;dfs(1);tim++; rt=build(1,tim,0);int m; m=read(); char opt[10];int x,y,z; while(m--) { scanf("%s",opt); switch (opt[0]) { case 'Q': query(read());break; case 'C': x=read(),change(x,read());break; case 'F': x=read(),addv(x,read());break; } } }