bzoj 3786 星系探索 dfs+splay
【BZOJ3786】星系探索
Description
物理學家小C的研究正遇到某個瓶頸。
他正在研究的是一個星系,這個星系中有n個星球,其中有一個主星球(方便起見我們默認其為1號星球),其余的所有星球均有且僅有一個依賴星球。主星球沒有依賴星球。
我們定義依賴關系如下:若星球a的依賴星球是b,則有星球a依賴星球b.此外,依賴關系具有傳遞性,即若星球a依賴星球b,星球b依賴星球c,則有星球a依賴星球c.
對於這個神秘的星系中,小C初步探究了它的性質,發現星球之間的依賴關系是無環的。並且從星球a出發只能直接到達它的依賴星球b.
每個星球i都有一個能量系數wi.小C想進行若幹次實驗,第i次實驗,他將從飛船上向星球di發射一個初始能量為0的能量收集器,能量收集器會從星球di開始前往主星球,並收集沿途每個星球的部分能量,收集能量的多少等於這個星球的能量系數。
但是星系的構成並不是一成不變的,某些時刻,星系可能由於某些復雜的原因發生變化。
有些時刻,某個星球能量激發,將使得所有依賴於它的星球以及他自己的能量系數均增加一個定值。還有可能在某些時刻,某個星球的依賴星球會發生變化,但變化後依然滿足依賴關系是無環的。
現在小C已經測定了時刻0時每個星球的能量系數,以及每個星球(除了主星球之外)的依賴星球。接下來的m個時刻,每個時刻都會發生一些事件。其中小C可能會進行若幹次實驗,對於他的每一次實驗,請你告訴他這一次實驗能量收集器的最終能量是多少。
Input
第一行一個整數n,表示星系的星球數。
接下來n-1行每行一個整數,分別表示星球2-n的依賴星球編號。
接下來一行n個整數,表示每個星球在時刻0時的初始能量系數wi.
接下來一行一個整數m,表示事件的總數。
事件分為以下三種類型。
(1)"Q di"表示小C要開始一次實驗,收集器的初始位置在星球di.
(2)"C xi yi"表示星球xi的依賴星球變為了星球yi.
(3)"F pi qi"表示星球pi能量激發,常數為qi.
Output
對於每一個事件類型為Q的事件,輸出一行一個整數,表示此次實驗的收集器最終能量。
Sample Input
31
1
4 5 7
5
Q 2
F 1 3
Q 2
C 2 3
Q 2
Sample Output
915
25
HINT
n<=100000,m<=300000,1<di,xi<=n,wi,qi<=100000.保證操作合法。
題意:給出一棵樹,要求有以下這些操作:
1.求出一個節點到根的點權和。
2.將一個節點的父親改變。
3.將一個子樹中的每一個節點都加上一個權值
題解:主要是操作2,不然樹鏈剖分可以強艹過,所以splay+dfs序即可。
1 #include<cstring> 2 #include<cmath> 3 #include<algorithm> 4 #include<iostream> 5 #include<cstdio> 6 #include<map> 7 #include<queue> 8 #include<vector> 9 #include<cstdlib> 10 #include<ctime> 11 12 #define ll long long 13 #define N 200007 14 using namespace std; 15 inline int read() 16 { 17 int x=0,f=1;char ch=getchar(); 18 while(ch>‘9‘||ch<‘0‘){if (ch==‘-‘) f=-1;ch=getchar();} 19 while(ch<=‘9‘&&ch>=‘0‘){x=(x<<3)+(x<<1)+ch-‘0‘;ch=getchar();} 20 return x*f; 21 } 22 23 int n,q; 24 int rt,top,tot; 25 int a[N],sta[N],fa[N],w[N],v[N],tag[N]; 26 int c[N][2],t[N][2],s[N][2]; 27 int cnt,head[N],next[N],rea[N]; 28 ll sum[N]; 29 30 void add(int u,int v) 31 { 32 next[++cnt]=head[u]; 33 head[u]=cnt; 34 rea[cnt]=v; 35 } 36 void dfs(int u) 37 { 38 v[t[u][0]=++tot]=a[u],w[tot]=1; 39 for (int i=head[u];i!=-1;i=next[i]) 40 { 41 int v=rea[i]; 42 if (!t[v][0]) 43 dfs(v); 44 } 45 v[t[u][1]=++tot]=-a[u],w[tot]=-1; 46 } 47 inline void pushup(int p) 48 { 49 if (!p) return; 50 int l=c[p][0],r=c[p][1]; 51 s[p][0]=s[l][0]+s[r][0]+(w[p]==1); 52 s[p][1]=s[l][1]+s[r][1]+(w[p]==-1); 53 sum[p]=sum[l]+sum[r]+v[p]; 54 } 55 inline void update(int p,ll z) 56 { 57 if (!p) return; 58 sum[p]+=(ll)(s[p][0]-s[p][1])*z; 59 v[p]+=w[p]*z; 60 tag[p]+=z; 61 } 62 inline void pushdown(int x) 63 { 64 if (!x) return; 65 if (!tag[x]) return; 66 update(c[x][0],tag[x]); 67 update(c[x][1],tag[x]); 68 tag[x]=0; 69 } 70 void rotate(int x,int &k) 71 { 72 int y=fa[x],z=fa[y],l,r; 73 if (c[y][1]==x) l=1;else l=0;r=l^1; 74 if (y!=k) c[z][c[z][1]==y]=x; 75 else k=x; 76 fa[x]=z,fa[y]=x,fa[c[x][r]]=y; 77 c[y][l]=c[x][r],c[x][r]=y; 78 pushup(x),pushup(y); 79 } 80 void splay(int x,int &k) 81 { 82 // cout<<" "<<x<<" "<<k<<endl; 83 for(int i=x;i;i=fa[i]) sta[++top]=i; 84 while (top) pushdown(sta[top--]); 85 while(x!=k) 86 { 87 //cout<<x<<" "<<k<<endl; 88 int y=fa[x],z=fa[y]; 89 if (y!=k) 90 { 91 if (c[z][0]==y^c[y][0]==x) rotate(x,k); 92 else rotate(y,k); 93 } 94 rotate(x,k); 95 } 96 } 97 inline int findmin(int x) 98 { 99 while(c[x][0]) 100 x=c[x][0]; 101 return x; 102 } 103 inline int findmax(int x) 104 { 105 while(c[x][1]) 106 x=c[x][1]; 107 return x; 108 } 109 void split(int x,int y) 110 { 111 splay(x,rt); 112 int t1=findmax(c[x][0]); 113 splay(y,rt); 114 int t2=findmin(c[y][1]); 115 splay(t1,rt); 116 splay(t2,c[t1][1]); 117 } 118 void build(int l,int r,int f) 119 { 120 if (l>r) return; 121 int x=(l+r)>>1; 122 fa[x]=f;c[f][x>f]=x; 123 if (l==r) 124 { 125 sum[x]=v[x]; 126 s[x][0]=w[x]==1; 127 s[x][1]=1-s[x][0]; 128 return; 129 } 130 build(l,x-1,x);build(x+1,r,x); 131 pushup(x); 132 } 133 int main() 134 { 135 memset(head,-1,sizeof(head)); 136 n=read(); 137 for (int i=2;i<=n;i++) 138 { 139 int x=read(); 140 add(x,i); 141 } 142 for (int i=1;i<=n;i++) 143 a[i]=read(); 144 tot=1,dfs(1);//增加哨兵。 145 build(1,2*n+2,0); 146 rt=(1+2*n+2)>>1; 147 148 q=read(); 149 while(q--) 150 { 151 char ch[2]; 152 scanf("%s",ch); 153 if (ch[0]==‘Q‘) 154 { 155 int x=read(); 156 splay(t[1][0],rt); 157 splay(t[x][0],c[rt][1]); 158 printf("%lld\n",sum[c[c[rt][1]][0]]+(ll)v[rt]+(ll)v[c[rt][1]]); 159 } 160 else if (ch[0]==‘F‘) 161 { 162 int x=read(),y=read(),z; 163 splay(t[x][0],rt);splay(t[x][1],c[rt][1]); 164 z=c[rt][1]; 165 v[rt]+=w[rt]*y;v[z]+=w[z]*y; 166 update(c[z][0],y); 167 pushup(z);pushup(rt); 168 } 169 else 170 { 171 int x=read(),y=read(),z,tmp; 172 split(t[x][0],t[x][1]); 173 z=c[rt][1];tmp=c[z][0];c[z][0]=0; 174 pushup(z);pushup(rt); 175 splay(t[y][0],rt); 176 splay(findmin(c[rt][1]),c[rt][1]); 177 z=c[rt][1];c[z][0]=tmp;fa[tmp]=z; 178 pushup(z);pushup(rt); 179 } 180 } 181 }
bzoj 3786 星系探索 dfs+splay