• 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
    ",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 }
  • 相关阅读:
    Ubuntu安装Cassandra
    Ubuntu安装中文输入法
    CoreOS, Kubernetes, etcd
    CountDownLatch, CyclicBarrier and Semaphore
    Java Primitives and Bits
    vue 和 webstorm(01) 之 基本入门 _fei
    ubuntu 命令窗口背景颜色 #300a24 _fei
    2345 看图王ad介绍----关闭广告 _fei
    PHP 使用 pdo 操作oracle数据库 报错 _fei
    PHP 使用 pdo 操作oracle数据库 报错 _fei
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/7045144.html
Copyright © 2020-2023  润新知