1. 程式人生 > >bzoj3786: 星系探索

bzoj3786: 星系探索

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: 星系探索