bzoj3786: 星系探索
阿新 • • 發佈:2018-03-10
pac fine pri mic int read math spl getchar
傳送門
一個裸的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
*/
View Code
·
bzoj3786: 星系探索