• bzoj 3786 星系探索 dfs+splay


    【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
    ",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 }
  • 相关阅读:
    在sql server中怎样获得正在执行的Sql查询
    在windows中使用VMWare安装Mac OS 10.7
    Scrspy 命令
    Windows Service 小品
    线程同步(一)
    线程基础必知必会(二)
    线程基础必知必会(一)
    准备工作与简介
    Python 正则表达式急速入门
    SQL Server 每日一题--每月销售额
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8082515.html
Copyright © 2020-2023  润新知