1. 程式人生 > >bzoj 3786 星系探索 dfs+splay

bzoj 3786 星系探索 dfs+splay

div spa 初步 cst 表示 -s for 之間 max

【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

3
1
1
4 5 7
5
Q 2
F 1 3
Q 2
C 2 3
Q 2

Sample Output

9
15
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