bzoj3786: 星系探索
一个裸的splay维护括号序列的题。
跟弹飞绵羊几乎一毛一样,只需把进栈的点权值设为w,出栈点权值设为-w即可。
多了一个子树加的操作,就把子树split出来,打上标记再merge回去就好了。
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
const int N=600007;
typedef long long LL;
using namespace std;
int n,m,val[N];
char o[10];
template<typename T>void read(T &x) {
char ch=getchar(); x=0; T f=1;
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=-1,ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}
int ecnt,fir[N],nx[N],to[N];
void add(int u,int v) {
nx[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
}
int dfn[2][N],v[N],f[N],dfs_clock,tot;
void dfs(int x) {
dfn[0][x]=++dfs_clock;
v[dfn[0][x]]=val[x];
f[dfn[0][x]]=1;
for(int i=fir[x];i;i=nx[i])
dfs(to[i]);
dfn[1][x]=++dfs_clock;
v[dfn[1][x]]=-val[x];
f[dfn[1][x]]=-1;
}
int p[N],ch[N][2];
LL sum[N],sumf[N],lz[N];
#define lc ch[x][0]
#define rc ch[x][1]
void update(int x) {
sum[x]=(LL)v[x]+sum[lc]+sum[rc];
sumf[x]=(LL)f[x]+sumf[lc]+sumf[rc];
}
void ADD(int x,int w) {
v[x]+=(LL)f[x]*w;
sum[x]+=sumf[x]*w;
lz[x]+=w;
}
void down(int x) {
if(!lz[x]) return;
if(lc) ADD(lc,lz[x]);
if(rc) ADD(rc,lz[x]);
lz[x]=0;
}
int build(int sz) {
if(!sz) return 0;
int ls,rs,x;
ls=build(sz>>1);
x=++tot;
rs=build(sz-(sz>>1)-1);
if(ls) p[ls]=x; lc=ls;
if(rs) p[rs]=x; rc=rs;
update(x);
return x;
}
void rotate(int x) {
int y=p[x],z=p[y],l=(x==ch[y][1]),r=l^1;
if(z) ch[z][y==ch[z][1]]=x; p[x]=z;
ch[y][l]=ch[x][r]; p[ch[x][r]]=y;
ch[x][r]=y; p[y]=x;
update(y); update(x);
}
void splay(int x,int FA=0) {
static int g[N],top=0,tp;
for(tp=x;tp!=FA;tp=p[tp]) g[++top]=tp;
g[++top]=tp;
while(top) down(g[top--]);
for(;p[x]!=FA;rotate(x)) {
int y=p[x],z=p[y];
if(z!=FA) ((x==ch[y][1])^(y==ch[z][1]))?rotate(x):rotate(y);
}
}
int pre(int x) {
splay(x); x=lc;
while(rc) x=rc;
return x;
}
int nxt(int x) {
splay(x); x=rc;
while(lc) x=lc;
return x;
}
int split(int x) {//x为左边 最后一个
splay(x); int y=rc;
rc=p[y]=0;
update(x); return y;
}
void merge(int x,int y) {
splay(x); splay(y);
while(rc) x=rc; splay(x);
rc=y; p[y]=x; update(x);
}
int main() {
#ifdef DEBUG
freopen(".in","r",stdin);
freopen(".out","w",stdout);
#endif
read(n);
for(int i=2;i<=n;i++) {
int fa; read(fa);
add(fa,i);
}
for(int i=1;i<=n;i++) read(val[i]);
dfs(1);
int x=2*n+1,y=2*n+2;
ch[x][1]=y; p[y]=x;
ch[y][0]=build(2*n); p[ch[y][0]]=y;
update(y); update(x);
read(m);
while(m--) {
scanf("%s",o);
int x,y,w; read(x);
if(o[0]=='Q') {
int z=nxt(dfn[0][x]);
splay(z);
printf("%lld\n",sum[ch[z][0]]);
}
else if(o[0]=='C') {
read(y);
int l=pre(dfn[0][x]);
split(l);
int r=split(dfn[1][x]);
merge(l,r);
split(dfn[0][y]);
merge(dfn[0][y],dfn[0][x]);
merge(dfn[0][x],dfn[1][y]);
}
else if(o[0]=='F') {
read(w);
int l=pre(dfn[0][x]);
split(l);
int r=split(dfn[1][x]);
splay(dfn[0][x]);
ADD(dfn[0][x],w);
merge(l,dfn[0][x]);
merge(dfn[0][x],r);
}
}
return 0;
}
/*
3
1
1
4 5 7
5
Q 2
F 1 3
Q 2
C 2 3
Q 2
*/
·