BZOJ3786: 星系探索
3786: 星系探索
Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 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
1
1
4 5 7
5
Q 2
F 1 3
Q 2
C 2 3
Q 2
Sample Output
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\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 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 }
代码: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 }