zoukankan      html  css  js  c++  java
  • BZOJ3786: 星系探索

    3786: 星系探索

    Time Limit: 40 Sec  Memory Limit: 256 MB
    Submit: 115  Solved: 34
    [Submit][Status]

    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.保证操作合法。


    Source

    题解:
    此题居然有鬼畜的换父亲操作。。。
    那么树的形态就变了。。。
    不过因为只要查询节点到根路径上的权值之和,类似于大都市meg,很容易想到dfs序,入点权值为正,出点权值为负。
    查询只要求前缀和即可。
    子树修改也很好搞。
    但要改父亲,我们用splay将整个子树平移。
    想想是可行的。
    但是实现!
    我们发现我们只知道节点,不知道它的rank,所以不能按原来的套路find 然后 splay
    而且此时父节点的标记还没有下传。
    然后暴力出奇迹。。。
    假设我们要分离出l,r的区间
    那我们 先splay(l,rt),并且在splay的时候先暴力把父节点的标记全部下传,类似于LCT。
    然后找出坐子树的最大节点,记为t1
    再splay(r,rt),找出右子树的最大节点,记为t2.
    最后splay(t1,rt),splay(t2,c[rt][1])即可。
    c[c[rt][1]][0]即为所提取的区间。
    又简单又粗暴。。。
    昨晚写好之后T成翔。今天忽然想到一个优化,打标记和查询的时候不需要提取区间,两个splay之后直接输出v[rt]+v[c[rt][1]]+sum[c[c[rt][1]][0]]即可。
    然后来了发现时限改了,变成40s了,昨天的程序就37s过了,加上优化32s。
    代码:37s
      1 #include<cstdio>
      2  
      3 #include<cstdlib>
      4  
      5 #include<cmath>
      6  
      7 #include<cstring>
      8  
      9 #include<algorithm>
     10  
     11 #include<iostream>
     12  
     13 #include<vector>
     14  
     15 #include<map>
     16  
     17 #include<set>
     18  
     19 #include<queue>
     20  
     21 #include<string>
     22  
     23 #define inf 1000000000
     24  
     25 #define maxn 250000+5
     26  
     27 #define maxm 500+100
     28  
     29 #define eps 1e-10
     30  
     31 #define ll long long
     32  
     33 #define pa pair<int,int>
     34  
     35 #define for0(i,n) for(int i=0;i<=(n);i++)
     36  
     37 #define for1(i,n) for(int i=1;i<=(n);i++)
     38  
     39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
     40  
     41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
     42  
     43 #define mod 1000000007
     44  
     45 using namespace std;
     46  
     47 inline int read()
     48  
     49 {
     50  
     51     int x=0,f=1;char ch=getchar();
     52  
     53     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     54  
     55     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
     56  
     57     return x*f;
     58  
     59 }
     60 int n,m,q,rt,top,tot,a[maxn],sta[maxn],head[maxn],fa[maxn],c[maxn][2],t[maxn][2],s[maxn][2],w[maxn],v[maxn],tag[maxn];
     61 ll sum[maxn];
     62 struct edge{int go,next;}e[maxn];
     63 inline void insert(int x,int y)
     64 {
     65     e[++tot]=(edge){y,head[x]};head[x]=tot;
     66 }
     67 inline void dfs(int x)
     68 {
     69     v[t[x][0]=++m]=a[x];w[m]=1;
     70     for(int i=head[x];i;i=e[i].next)
     71         if(!t[e[i].go][0])dfs(e[i].go);
     72     v[t[x][1]=++m]=-a[x];w[m]=-1;
     73 }
     74 inline void pushup(int x)
     75 {
     76     if(!x)return;
     77     int l=c[x][0],r=c[x][1];
     78     s[x][0]=s[l][0]+s[r][0]+(w[x]==1);
     79     s[x][1]=s[l][1]+s[r][1]+(w[x]==-1);
     80     sum[x]=sum[l]+sum[r]+(ll)v[x];
     81 }
     82 inline void update(int x,ll z)
     83 {
     84     if(!x)return;
     85     sum[x]+=(ll)(s[x][0]-s[x][1])*z;v[x]+=w[x]*z;
     86     tag[x]+=z;
     87 }
     88 inline void pushdown(int x)
     89 {
     90     if(!x)return;
     91     if(!tag[x])return;
     92     update(c[x][0],tag[x]);
     93     update(c[x][1],tag[x]);
     94     tag[x]=0;
     95 }
     96 inline void rotate(int x,int &k)
     97 {
     98     int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1;
     99     if(y!=k)c[z][c[z][1]==y]=x;else k=x;
    100     fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
    101     c[y][l]=c[x][r];c[x][r]=y;
    102     pushup(y);pushup(x);
    103 }
    104 inline void splay(int x,int &k)
    105 {
    106     for(int i=x;i;i=fa[i])sta[++top]=i;
    107     while(top)pushdown(sta[top--]);
    108     while(x!=k)
    109     {
    110        int y=fa[x],z=fa[y];
    111        if(y!=k)
    112        {
    113           if(c[z][0]==y^c[y][0]==x)rotate(x,k);else rotate(y,k);
    114        }
    115        rotate(x,k);
    116     }
    117 }  
    118 inline int findmin(int x)
    119 {
    120     while(c[x][0])x=c[x][0];
    121     return x;
    122 }
    123 inline int findmax(int x)
    124 {
    125     while(c[x][1])x=c[x][1];
    126     return x;
    127 }
    128 inline void split(int x,int y)
    129 {
    130     splay(x,rt);
    131     int t1=findmax(c[x][0]);
    132     splay(y,rt);
    133     int t2=findmin(c[y][1]);
    134     splay(t1,rt);
    135     splay(t2,c[t1][1]);
    136 }
    137 inline void build(int l,int r,int f)
    138 {
    139     if(l>r)return;
    140     int x=(l+r)>>1;
    141     fa[x]=f;c[f][x>f]=x;
    142     if(l==r){sum[x]=v[x];s[x][0]=w[x]==1;s[x][1]=1-s[x][0];return;}
    143     build(l,x-1,x);build(x+1,r,x);
    144     pushup(x);
    145 }
    146  
    147 int main()
    148  
    149 {
    150  
    151     n=read();
    152     for2(i,2,n)insert(read(),i);
    153     for1(i,n)a[i]=read();m=1;
    154     dfs(1);
    155     build(1,2*n+2,0);rt=(1+2*n+2)>>1;
    156     q=read();
    157     while(q--)
    158     {
    159         char ch=getchar();
    160         while(ch!='Q'&&ch!='C'&&ch!='F')ch=getchar();
    161         if(ch=='Q')
    162         {
    163             int x=read();
    164             split(t[1][0],t[x][0]);
    165             printf("%lld
    ",sum[c[c[rt][1]][0]]);
    166         }
    167         else if(ch=='F')
    168         {
    169             int x=read();
    170             split(t[x][0],t[x][1]);
    171             int z=c[rt][1];
    172             update(c[z][0],read());
    173             pushup(z);pushup(rt);
    174         }
    175         else
    176         {
    177             int x=read(),y=read();
    178             split(t[x][0],t[x][1]);
    179             int z=c[rt][1],tmp=c[z][0];c[z][0]=0;
    180             pushup(z);pushup(rt);
    181             splay(t[y][0],rt);splay(findmin(c[rt][1]),c[rt][1]);
    182             z=c[rt][1];c[z][0]=tmp;fa[tmp]=z;
    183             pushup(z);pushup(rt);
    184         }
    185     }
    186  
    187     return 0;
    188  
    189 } 
    View Code

    代码:32s

      1 #include<cstdio>
      2 
      3 #include<cstdlib>
      4 
      5 #include<cmath>
      6 
      7 #include<cstring>
      8 
      9 #include<algorithm>
     10 
     11 #include<iostream>
     12 
     13 #include<vector>
     14 
     15 #include<map>
     16 
     17 #include<set>
     18 
     19 #include<queue>
     20 
     21 #include<string>
     22 
     23 #define inf 1000000000
     24 
     25 #define maxn 250000+5
     26 
     27 #define maxm 500+100
     28 
     29 #define eps 1e-10
     30 
     31 #define ll long long
     32 
     33 #define pa pair<int,int>
     34 
     35 #define for0(i,n) for(int i=0;i<=(n);i++)
     36 
     37 #define for1(i,n) for(int i=1;i<=(n);i++)
     38 
     39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
     40 
     41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
     42 
     43 #define mod 1000000007
     44 
     45 using namespace std;
     46 
     47 inline int read()
     48 
     49 {
     50 
     51     int x=0,f=1;char ch=getchar();
     52 
     53     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     54 
     55     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
     56 
     57     return x*f;
     58 
     59 }
     60 int n,m,q,rt,top,tot,a[maxn],sta[maxn],head[maxn],fa[maxn],c[maxn][2],t[maxn][2],s[maxn][2],w[maxn],v[maxn],tag[maxn];
     61 ll sum[maxn];
     62 struct edge{int go,next;}e[maxn];
     63 inline void insert(int x,int y)
     64 {
     65     e[++tot]=(edge){y,head[x]};head[x]=tot;
     66 }
     67 inline void dfs(int x)
     68 {
     69     v[t[x][0]=++m]=a[x];w[m]=1;
     70     for(int i=head[x];i;i=e[i].next)
     71         if(!t[e[i].go][0])dfs(e[i].go);
     72     v[t[x][1]=++m]=-a[x];w[m]=-1;
     73 }
     74 inline void pushup(int x)
     75 {
     76     if(!x)return;
     77     int l=c[x][0],r=c[x][1];
     78     s[x][0]=s[l][0]+s[r][0]+(w[x]==1);
     79     s[x][1]=s[l][1]+s[r][1]+(w[x]==-1);
     80     sum[x]=sum[l]+sum[r]+(ll)v[x];
     81 }
     82 inline void update(int x,ll z)
     83 {
     84     if(!x)return;
     85     sum[x]+=(ll)(s[x][0]-s[x][1])*z;v[x]+=w[x]*z;
     86     tag[x]+=z;
     87 }
     88 inline void pushdown(int x)
     89 {
     90     if(!x)return;
     91     if(!tag[x])return;
     92     update(c[x][0],tag[x]);
     93     update(c[x][1],tag[x]);
     94     tag[x]=0;
     95 }
     96 inline void rotate(int x,int &k)
     97 {
     98     int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1;
     99     if(y!=k)c[z][c[z][1]==y]=x;else k=x;
    100     fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
    101     c[y][l]=c[x][r];c[x][r]=y;
    102     pushup(y);pushup(x);
    103 }
    104 inline void splay(int x,int &k)
    105 {
    106     for(int i=x;i;i=fa[i])sta[++top]=i;
    107     while(top)pushdown(sta[top--]);
    108     while(x!=k)
    109     {
    110        int y=fa[x],z=fa[y];
    111        if(y!=k)
    112        {
    113           if(c[z][0]==y^c[y][0]==x)rotate(x,k);else rotate(y,k);
    114        }
    115        rotate(x,k);
    116     }
    117 }    
    118 inline int findmin(int x)
    119 {
    120     while(c[x][0])x=c[x][0];
    121     return x;
    122 }
    123 inline int findmax(int x)
    124 {
    125     while(c[x][1])x=c[x][1];
    126     return x;
    127 }
    128 inline void split(int x,int y)
    129 {
    130     splay(x,rt);
    131     int t1=findmax(c[x][0]);
    132     splay(y,rt);
    133     int t2=findmin(c[y][1]);
    134     splay(t1,rt);
    135     splay(t2,c[t1][1]);
    136 }
    137 inline void build(int l,int r,int f)
    138 {
    139     if(l>r)return;
    140     int x=(l+r)>>1;
    141     fa[x]=f;c[f][x>f]=x;
    142     if(l==r){sum[x]=v[x];s[x][0]=w[x]==1;s[x][1]=1-s[x][0];return;}
    143     build(l,x-1,x);build(x+1,r,x);
    144     pushup(x);
    145 }
    146 
    147 int main()
    148 
    149 {
    150 
    151     freopen("input.txt","r",stdin);
    152 
    153     freopen("output.txt","w",stdout);
    154 
    155     n=read();
    156     for2(i,2,n)insert(read(),i);
    157     for1(i,n)a[i]=read();m=1;
    158     dfs(1);
    159     build(1,2*n+2,0);rt=(1+2*n+2)>>1;
    160     q=read();
    161     while(q--)
    162     {
    163         char ch=getchar();
    164         while(ch!='Q'&&ch!='C'&&ch!='F')ch=getchar();
    165         if(ch=='Q')
    166         {
    167             int x=read();
    168             splay(t[1][0],rt);splay(t[x][0],c[rt][1]);
    169             printf("%lld
    ",sum[c[c[rt][1]][0]]+(ll)v[rt]+(ll)v[c[rt][1]]);
    170         }
    171         else if(ch=='F')
    172         {
    173             int x=read(),y=read();
    174             splay(t[x][0],rt);splay(t[x][1],c[rt][1]);
    175             int z=c[rt][1];
    176             v[rt]+=w[rt]*y;v[z]+=w[z]*y;
    177             update(c[z][0],y);
    178             pushup(z);pushup(rt);
    179         }
    180         else 
    181         {
    182             int x=read(),y=read();
    183             split(t[x][0],t[x][1]);
    184             int z=c[rt][1],tmp=c[z][0];c[z][0]=0;
    185             pushup(z);pushup(rt);
    186             splay(t[y][0],rt);splay(findmin(c[rt][1]),c[rt][1]);
    187             z=c[rt][1];c[z][0]=tmp;fa[tmp]=z;
    188             pushup(z);pushup(rt);
    189         }
    190     }
    191 
    192     return 0;
    193 
    194 } 
    View Code
  • 相关阅读:
    Spring Controller参数为空串的处理方式
    netstat用法
    zookeeper的配置项
    C++ Lambda表达式用法
    java命令行运行jar里的main类
    Random的nextInt用法
    【JAVA】删除某个目录及目录下的所有子目录和文件
    Centos7设置keepAlived开机自启动
    linux设置nginx开机自启动
    window.open()方法
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/4139068.html
Copyright © 2011-2022 走看看