bzoj3786星系探索(splay维护dfs序)

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

解题思路:

这道题假如没有换根操作,那么就是一入栈出栈序的裸题,也就是,对于子树更改节点,在入栈出栈序上这个点入栈处加入操作,在出栈处取消操作(区间加和就好)。而查询操作,则是查询某个点入栈序的前缀和。验证这个方法的正确性:如果这个点i是点j的子树中的点,那么就能查询到加入操作,而查询不到取消操作。那么就是说,如果查询前缀时,若同时查询到了入栈和出栈,那么操作就会被取消。

对于这道题,区间和可以被认为是子树权值和,只要子树中同时有入栈和出栈,那么权值上就没有这个点。

那么就维护一下入栈出栈序。

用splay维护入栈出栈序,splay的中序遍历就是入栈出栈序。

考虑操作Q,查询入栈出栈序的前缀和。

那么就是将这个点的入栈位置旋转到根,答案就是左子树权值和+根权。

考虑操作C,将一段入栈出栈序插入到另一段入栈出栈序之中。

那么就先将这段入栈出栈序的前驱旋转到根,再将后继旋转至根的儿子。

那么我们就将这棵树像挤痘痘一样挤了出来。

然后将根摘除并pushup两次愈合伤口。

再旋转出要加的位置栽上,再pushup两次使其无缝连接^_^

考虑操作F,将子树加权。

懒惰标记旋转时下传即可。

注意:

1.由于入栈出栈序一一对应,取消操作只要是加入操作的相反数即可。

2.子树内求和懒惰标记时总和为入栈个数。

代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define lll tr[spc].ch[0]
  5 #define rrr tr[spc].ch[1]
  6 #define ls ch[0]
  7 #define rs ch[1]
  8 typedef long long lnt;
  9 const int N=300000;
 10 struct pnt{
 11     int hd;
 12     int ind;
 13     int oud;
 14     lnt vl;
 15 }p[N];
 16 struct ent{
 17     int twd;
 18     int lst;
 19 }e[N];
 20 struct trnt{
 21     int ch[2];
 22     int fa;
 23     lnt val;
 24     lnt sum;
 25     lnt wgt;
 26     lnt ctr;
 27     lnt lzt;
 28     lnt fst;
 29     lnt chr;
 30 }tr[N],stdtr;
 31 int n,m,cnt,siz;
 32 int root;
 33 int ic;
 34 int plc[N];
 35 int dnf[N];
 36 char cmd[10];
 37 int vls(int x)
 38 {
 39     if(x==0||x==ic+1)
 40         return 0;
 41     return (p[dnf[x]].ind==x)?1:-1;
 42 }
 43 bool whc(int spc)
 44 {
 45     return tr[tr[spc].fa].rs==spc;
 46 }
 47 void new_point(int spc,int i)
 48 {
 49     tr[spc]=stdtr;
 50     int cmdlp=vls(i);
 51     plc[i]=spc;
 52     tr[spc].chr=dnf[i];
 53     tr[spc].val=p[dnf[i]].vl*cmdlp;
 54     tr[spc].ctr=cmdlp;
 55     return ;
 56 }
 57 void ade(int f,int t)
 58 {
 59     cnt++;
 60     e[cnt].twd=t;
 61     e[cnt].lst=p[f].hd;
 62     p[f].hd=cnt;
 63     return ;
 64 }
 65 void dfs(int x)
 66 {
 67     p[x].ind=++ic;
 68     dnf[ic]=x;
 69     for(int i=p[x].hd;i;i=e[i].lst)
 70         dfs(e[i].twd);
 71     p[x].oud=++ic;
 72     dnf[ic]=x;
 73     return ;
 74 }
 75 void pushup(int spc)
 76 {
 77     tr[spc].wgt=tr[lll].wgt+tr[rrr].wgt+1;
 78     tr[spc].sum=tr[lll].sum+tr[rrr].sum+tr[spc].val;
 79     tr[spc].fst=tr[lll].fst+tr[rrr].fst+tr[spc].ctr;
 80     return ;
 81 }
 82 void FFT(lnt spc,lnt k)
 83 {
 84     if(!spc)
 85         return ;
 86     tr[spc].lzt+=k;
 87     tr[spc].sum+=k*tr[spc].fst;
 88     tr[spc].val+=k*tr[spc].ctr;
 89     return ;
 90 }
 91 void pushdown(int spc)
 92 {
 93     if(tr[spc].lzt)
 94     {
 95         FFT(lll,tr[spc].lzt);
 96         FFT(rrr,tr[spc].lzt);
 97         tr[spc].lzt=0;
 98     }
 99     return ;
100 }
101 void build(int l,int r,int &spc,int f)
102 {
103     if(l>r)
104         return ;
105     int mid=(l+r)>>1;
106     spc=++siz;
107     new_point(spc,mid);
108     tr[spc].fa=f;
109     build(l,mid-1,lll,spc);
110     build(mid+1,r,rrr,spc);
111     pushup(spc);
112     return ;
113 }
114 void rotate(int spc)
115 {
116     int f=tr[spc].fa;
117     pushdown(f);
118     pushdown(spc);
119     bool k=whc(spc);
120     tr[f].ch[k]=tr[spc].ch[!k];
121     tr[spc].ch[!k]=f;
122     tr[tr[f].fa].ch[whc(f)]=spc;
123     tr[spc].fa=tr[f].fa;
124     tr[f].fa=spc;
125     tr[tr[f].ch[k]].fa=f;
126     pushup(spc);
127     pushup(f);
128     return ;
129 }
130 void splay(int spc,int f)
131 {
132     while(tr[spc].fa!=f)
133     {
134         int ft=tr[spc].fa;
135         if(tr[ft].fa==f)
136         {
137             rotate(spc);
138             break;
139         }
140         if(whc(ft)^whc(spc))
141             rotate(spc);
142         else
143             rotate(ft);
144         rotate(spc);
145     }
146     if(!f)
147         root=spc;
148     return ;
149 }
150 int place(int spc,int cmd)//0 qianqu
151 {
152     if(tr[spc].ch[cmd])
153     {
154         spc=tr[spc].ch[cmd];
155         while(tr[spc].ch[1-cmd])
156             spc=tr[spc].ch[1-cmd];
157         return spc;
158     }
159     while(whc(spc)==(bool)cmd)
160         spc=tr[spc].fa;
161     return tr[spc].fa;
162 }
163 int main()
164 {
165     scanf("%d",&n);
166     for(int i=2;i<=n;i++)
167     {
168         int x;
169         scanf("%d",&x);
170         ade(x,i);
171     }
172     for(int i=1;i<=n;i++)
173         scanf("%lld",&p[i].vl);
174     scanf("%d",&m);
175     dfs(1);
176     build(0,ic+1,root,0);
177     while(m--)
178     {
179         scanf("%s",cmd);
180         if(cmd[0]=='Q')
181         {
182             int x;
183             scanf("%d",&x);
184             splay(plc[p[x].ind],0);
185             printf("%lld\n",tr[root].val+tr[tr[root].ls].sum);
186         }else if(cmd[0]=='C')
187         {
188             int x,y;
189             scanf("%d%d",&x,&y);
190             splay(place(plc[p[x].ind],0),0);
191             splay(place(plc[p[x].oud],1),root);
192             int tmp=tr[tr[root].rs].ls;
193             tr[tr[root].rs].ls=0;
194             pushup(tr[root].rs);
195             pushup(root);
196             splay(plc[p[y].ind],0);
197             splay(place(plc[p[y].ind],1),root);
198             tr[tr[root].rs].ls=tmp;
199             tr[tmp].fa=tr[root].rs;
200             pushup(tr[root].rs);
201             pushup(root);
202         }else
203         {
204             lnt x,y;
205             scanf("%lld%lld",&x,&y);
206             splay(place(plc[p[x].ind],0),0);
207             splay(place(plc[p[x].oud],1),root);
208             int spc=tr[tr[root].rs].ls;
209             tr[spc].lzt+=y;
210             tr[spc].sum+=tr[spc].fst*y;
211             tr[spc].val+=tr[spc].ctr*y;
212         }
213            
214     }
215     return 0;
216 }

 

posted @ 2018-09-07 12:51  Unstoppable728  阅读(429)  评论(0编辑  收藏  举报