Bzoj3786 星系探索
Posted SilverNebula
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Bzoj3786 星系探索相关的知识,希望对你有一定的参考价值。
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
1
1
4 5 7
5
Q 2
F 1 3
Q 2
C 2 3
Q 2
Sample Output
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 星系探索的主要内容,如果未能解决你的问题,请参考以下文章