zoukankan      html  css  js  c++  java
  • bzoj3786星系探索 splay

    3786: 星系探索

    Time Limit: 40 Sec  Memory Limit: 256 MB
    Submit: 1314  Solved: 425
    [Submit][Status][Discuss]

    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的理解加深了很多
    求路径的和,首先应该想到树转序列
    但如果用链剖+线段树,是无法修改父子关系的
    看了看题解,说的是splay+dfs序,感觉美妙
    可以记录一颗子树的入点和出点,这样就把一颗子树转化成了一段区间,如果修改父子关系,整体把某颗子树区间移动到一个节点后面
    如果要求树上点到根的权值和,可以选择差分,入点+ 出点-
    维护子树需要维护子树中有多少入点和出点
    一颗子树整体加上某个值时,标记区间,区间的根节点 +val*(入点数-出点数)

      1 #include<iostream>  
      2 #include<cstdio>  
      3 #include<cstring>  
      4 #include<algorithm>  
      5 #define F(i,a,b) for(int i=a;i<=b;i++)
      6 #define ll long long  
      7 #define maxn 200100  
      8 using namespace std;  
      9 int n,q,rt,top,cnt,tot;  
     10 int a[maxn],sta[maxn],head[maxn],fa[maxn],w[maxn],v[maxn],tag[maxn];  
     11 int c[maxn][2],t[maxn][2],s[maxn][2];  
     12 ll sum[maxn];  
     13 struct edge_type  
     14 {  
     15     int next,to;  
     16 }e[maxn];  
     17 inline int read()  
     18 {  
     19     int x=0,f=1;char ch=getchar();  
     20     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}  
     21     while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}  
     22     return x*f;  
     23 }  
     24 inline void add_edge(int x,int y)  
     25 {  
     26     e[++cnt]=(edge_type){head[x],y};head[x]=cnt;  
     27 }  
     28 inline void dfs(int x)  
     29 {  
     30     v[t[x][0]=++tot]=a[x];w[tot]=1;  
     31     for(int i=head[x];i;i=e[i].next) if (!t[e[i].to][0]) dfs(e[i].to);  
     32     v[t[x][1]=++tot]=-a[x];w[tot]=-1;  
     33 }  
     34 inline void pushup(int x)  
     35 {  
     36     if (!x) return;  
     37     int l=c[x][0],r=c[x][1];  
     38     s[x][0]=s[l][0]+s[r][0]+(w[x]==1);  
     39     s[x][1]=s[l][1]+s[r][1]+(w[x]==-1);  
     40     sum[x]=sum[l]+sum[r]+(ll)v[x];  
     41 }  
     42 inline void update(int x,ll z)  
     43 {  
     44     if (!x) return;  
     45     sum[x]+=(ll)(s[x][0]-s[x][1])*z;  
     46     v[x]+=w[x]*z;  
     47     tag[x]+=z;  
     48 }  
     49 inline void pushdown(int x)  
     50 {  
     51     if (!x) return;  
     52     if (!tag[x]) return;  
     53     update(c[x][0],tag[x]);  
     54     update(c[x][1],tag[x]);  
     55     tag[x]=0;  
     56 }  
     57 inline void rotate(int x,int &k)  
     58 {  
     59     int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1;  
     60     if (y!=k) c[z][c[z][1]==y]=x;else k=x;  
     61     fa[x]=z;fa[y]=x;fa[c[x][r]]=y;  
     62     c[y][l]=c[x][r];c[x][r]=y;  
     63     pushup(y);pushup(x);  
     64 }  
     65 inline void splay(int x,int &k)  
     66 {  
     67     for(int i=x;i;i=fa[i]) sta[++top]=i;  
     68     while (top) pushdown(sta[top--]);  
     69     while (x!=k)  
     70     {  
     71         int y=fa[x],z=fa[y];  
     72         if (y!=k)  
     73         {  
     74             if ((c[z][0]==y)^(c[y][0]==x)) rotate(x,k);  
     75             else rotate(y,k);  
     76         }  
     77         rotate(x,k);  
     78     }  
     79 }  
     80 inline int findmin(int x)  
     81 {  
     82     while (c[x][0]) x=c[x][0];  
     83     return x;  
     84 }  
     85 inline int findmax(int x)  
     86 {  
     87     while (c[x][1]) x=c[x][1];  
     88     return x;  
     89 }  
     90 inline void split(int x,int y)  
     91 {  
     92     splay(x,rt);  
     93     int t1=findmax(c[x][0]);  
     94     splay(y,rt);  
     95     int t2=findmin(c[y][1]);  
     96     splay(t1,rt);  
     97     splay(t2,c[t1][1]);  
     98 }  
     99 inline void build(int l,int r,int f)  
    100 {  
    101     if (l>r) return;  
    102     int x=(l+r)>>1;  
    103     fa[x]=f;c[f][x>f]=x;  
    104     if (l==r){sum[x]=v[x];s[x][0]=w[x]==1;s[x][1]=1-s[x][0];return;}  
    105     build(l,x-1,x);build(x+1,r,x);  
    106     pushup(x);  
    107 }  
    108 int main()  
    109 {  
    110     n=read();  
    111     F(i,2,n){int x=read();add_edge(x,i);}  
    112     F(i,1,n) a[i]=read();  
    113     tot=1;dfs(1);  
    114     build(1,2*n+2,0);  
    115     rt=n+1;  
    116     q=read();  
    117     while (q--)  
    118     {  
    119         char ch=getchar();  
    120         while (ch<'A'||ch>'Z') ch=getchar();  
    121         if (ch=='Q')  
    122         {  
    123             int x=read();  
    124             splay(t[1][0],rt);splay(t[x][0],c[rt][1]);  
    125             printf("%lld
    ",sum[c[c[rt][1]][0]]+(ll)v[rt]+(ll)v[c[rt][1]]);  
    126         }  
    127         else if (ch=='F')  
    128         {  
    129             int x=read(),y=read(),z;  
    130             splay(t[x][0],rt);splay(t[x][1],c[rt][1]);  
    131             z=c[rt][1];  
    132             v[rt]+=w[rt]*y;v[z]+=w[z]*y;  
    133             update(c[z][0],y);  
    134             pushup(z);pushup(rt);  
    135         }  
    136         else  
    137         {  
    138             int x=read(),y=read(),z,tmp;  
    139             split(t[x][0],t[x][1]);  
    140             z=c[rt][1];tmp=c[z][0];c[z][0]=0;  
    141             pushup(z);pushup(rt);  
    142             splay(t[y][0],rt);  
    143             splay(findmin(c[rt][1]),c[rt][1]);  
    144             z=c[rt][1];c[z][0]=tmp;fa[tmp]=z;  
    145             pushup(z);pushup(rt);  
    146         }  
    147     }  
    148     return 0;  
    149 }  
     
  • 相关阅读:
    Linux搭建maven私服
    eclipse提交项目到GitHub
    eclipse安装sts插件
    idea配置jdk
    C语言之链表————(转载)
    链表(创建,插入,删除和打印输出(转载)
    C语言之链表
    ARM 之LCD和LCD控制器
    ARM的两种启动方式 (NAND FLASH. NOR FLASH)
    ARM 汇编器对C的扩展
  • 原文地址:https://www.cnblogs.com/wsy01/p/8098988.html
Copyright © 2011-2022 走看看