首页 > 代码库 > BZOJ3786: 星系探索

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

By 佚名上传

题解:
此题居然有鬼畜的换父亲操作。。。
那么树的形态就变了。。。
不过因为只要查询节点到根路径上的权值之和,类似于大都市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\n",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         else176         {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\n",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

 

BZOJ3786: 星系探索