Bzoj3786 星系探索

Posted SilverNebula

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Bzoj3786 星系探索相关的知识,希望对你有一定的参考价值。

 

Time Limit: 40 Sec  Memory Limit: 256 MB
Submit: 1036  Solved: 342

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.保证操作合法。注意w_i>=0

Source

 

树 Splay维护DFS序

填了一个远古巨坑。

很久很久以前从thwfhk dalao那里听说了自适应top-tree的写法和ETT的写法,想着什么时候学了写一下,于是一直拖到了现在。

感觉这两个东西可能永远也不会学了,于是老实用Splay做吧2333

 

记录每个结点的入栈出栈序,为入栈/出栈的序号各开一个结点,入的结点权值为正,出的结点权值为负,这样一进一出,权值就差分抵消了,从1到in[x]这段区间的权值和就是从root到x结点的路径的权值和。

移动子树的时候,只要把从in[x]到out[x]的这段序列切下来,接到目标结点y的dfs序区间中(为了方便,统一接到in[y]的后面),用splay实现很方便。

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<queue>
  6 #define LL long long
  7 using namespace std;
  8 const int mxn=210010;
  9 int read(){
 10     int x=0,f=1;char ch=getchar();
 11     while(ch<0 || ch>9){if(ch==-)f=-1;ch=getchar();}
 12     while(ch>=0 && ch<=9){x=x*10-0+ch;ch=getchar();}
 13     return x*f;
 14 }
 15 struct edge{
 16     int v,nxt;
 17 }e[mxn<<1];
 18 int hd[mxn],mct=0;
 19 void add_edge(int u,int v){
 20     e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return;
 21 }
 22 int ind[mxn],out[mxn],dtime=0;
 23 int st[mxn],top=0;
 24 int w[mxn];
 25 int L[mxn],R[mxn],D[mxn];
 26 //入的数量 出的数量 标记 
 27 struct node{
 28     int ch[2],fa;
 29     LL val,smm;
 30     LL mk;int sz;
 31 }t[mxn];
 32 int rot;
 33 void DFS(int u){
 34     ind[u]=++dtime;D[dtime]=1;t[dtime].val=D[dtime]*w[u];
 35     for(int i=hd[u];i;i=e[i].nxt)
 36         DFS(e[i].v);
 37     out[u]=++dtime;D[dtime]=-1;t[dtime].val=D[dtime]*w[u];
 38     return;
 39 }
 40 void update(int x,int v){
 41     if(!x || !v)return;
 42     t[x].val+=D[x]*v;t[x].smm+=(L[x]-R[x])*(LL)v;
 43     t[x].mk+=v;
 44     return;
 45 }
 46 void PD(int x){
 47     if(!x)return;
 48     update(t[x].ch[0],t[x].mk);
 49     update(t[x].ch[1],t[x].mk);
 50     t[x].mk=0;
 51     return;
 52 }
 53 inline void pushup(int x){
 54     if(!x)return;
 55     int lc=t[x].ch[0],rc=t[x].ch[1];
 56     t[x].smm=t[lc].smm+t[x].val+t[rc].smm;
 57     L[x]=L[lc]+L[rc]+(D[x]==1);
 58     R[x]=R[lc]+R[rc]+(D[x]!=1);
 59     t[x].sz=t[lc].sz+t[rc].sz+1;
 60     return;
 61 }
 62 void rotate(int x,int &k){
 63     int y=t[x].fa,z=t[y].fa,lc,rc;
 64     if(t[y].ch[0]==x)lc=0;else lc=1;rc=lc^1;
 65     if(y==k)k=x;
 66     else t[z].ch[t[z].ch[1]==y]=x;
 67     t[x].fa=z; t[y].fa=x;
 68     t[t[x].ch[rc]].fa=y;
 69     t[y].ch[lc]=t[x].ch[rc];t[x].ch[rc]=y;
 70     pushup(y);
 71     return;
 72 }
 73 int stk[mxn],top1=0;
 74 void Splay(int x,int &k){
 75     stk[top1=1]=x;
 76     for(int i=x;t[i].fa;i=t[i].fa)stk[++top1]=t[i].fa;
 77     while(top1)PD(stk[top1--]);
 78     while(x!=k){
 79         int y=t[x].fa,z=t[y].fa;
 80         if(y!=k){
 81             if((t[z].ch[0]==y)^(t[y].ch[0]==x))rotate(x,k);
 82             else rotate(y,k);
 83         }
 84         rotate(x,k);
 85     }
 86     pushup(x);
 87     return;
 88 }
 89 /*
 90 inline int find(int x,int num){
 91     PD(x);
 92     int lc=t[x].ch[0],rc=t[x].ch[1];
 93     if(t[lc].size>=num)return find(lc,num);
 94     if(t[lc].size+1==num)return x;
 95     return find(rc,num-t[lc].size-1);
 96 }*/
 97 int find_max(int x){
 98     while(t[x].ch[1])x=t[x].ch[1];return x;
 99 }
100 int find_min(int x){
101     while(t[x].ch[0])x=t[x].ch[0];return x;
102 }
103 inline void split(int x,int y){
104     Splay(x,rot);
105     int l=find_max(t[x].ch[0]);
106     Splay(y,rot);
107     int r=find_min(t[y].ch[1]);
108     Splay(l,rot);Splay(r,t[l].ch[1]);
109     return;
110 }
111 int Build(int l,int r,int fa){
112     if(l>r)return 0;
113     int mid=(l+r)>>1,res=mid;
114     t[res].fa=fa;
115     if(l==r){
116         t[res].smm=t[res].val;
117         L[res]=(D[res]==1);    R[res]=L[res]^1;
118         return res;
119     }
120     t[res].ch[0]=Build(l,mid-1,res);
121     t[res].ch[1]=Build(mid+1,r,res);
122     pushup(res);
123     return res;
124 }
125 void query(int x){
126     Splay(ind[1],rot);
127     Splay(ind[x],t[rot].ch[1]);
128     LL ans=t[ind[1]].val+t[ind[x]].val+t[t[ind[x]].ch[0]].smm;
129     printf("%lld\n",ans);
130     return;
131 }
132 void power(){
133     int x=read();int v=read();
134     Splay(ind[x],rot);
135     Splay(out[x],t[rot].ch[1]);
136     t[ind[x]].val+=D[ind[x]]*v;t[out[x]].val+=D[out[x]]*v;
137     update(t[out[x]].ch[0],v);
138     pushup(t[rot].ch[1]);pushup(rot);
139     return;
140 }
141 int n,m;
142 int main(){
143     int i,j,x,y;
144     n=read();
145     for(i=2;i<=n;i++){
146         x=read();add_edge(x,i);
147     }
148     for(i=1;i<=n;i++)w[i]=read();
149     DFS(1);
150     rot=Build(1,n<<1,0);
151     m=read();
152     char ch[3];
153     while(m--){
154         scanf("%s",ch);
155         switch(ch[0]){
156             case Q:{x=read();query(x);break;}
157             case C:{
158                 x=read();y=read();//x to y;
159                 split(ind[x],out[x]);
160                 int fa=t[rot].ch[1],tmp=t[fa].ch[0];
161                 t[fa].ch[0]=0;
162                 pushup(fa);pushup(rot);
163                 Splay(ind[y],rot);
164                 Splay(find_min(t[rot].ch[1]),t[rot].ch[1]);
165                 fa=t[rot].ch[1];
166                 t[fa].ch[0]=tmp;
167                 t[tmp].fa=fa; pushup(fa);pushup(rot);
168                 break;
169             }
170             case F:{power();break;}
171         }
172     }
173     return 0;
174 }

 

以上是关于Bzoj3786 星系探索的主要内容,如果未能解决你的问题,请参考以下文章

[BZOJ3786]星系探索(伪ETT)

BZOJ-3786星系探索 Splay + DFS序

Bzoj3786 星系探索

bzoj 3786 星系探索 dfs+splay

BZOJ3786星系探索 DFS序+Splay

bzoj3786星系探索