3786: 星系探索
Time Limit: 40 Sec Memory Limit: 256 MB
Submit: 1524 Solved: 484
[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
sol:
这题卡常数,请尽量手动updata
由于要对子树修改,所以不能lct了。因为这题并不会出现森林,我们考虑使用splay维护dfs序,点进栈时设为1,退栈时设为-1,那么他到根的前缀和就是他到根的路径和。这题只要维护子树和和子树系数和就好了。
思考一下这题的加强版,如果询问的是任意 u,v路径的权值和的话怎么做。
可以用u到根的权值和+v到根的-lca到根-fa[lca]到根的
那么问题就变成了怎么求lca了。
用lct维护一下树的形态,然后用access求lca即可。其余代码不变。
T的代码
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cmath>
using namespace std;
typedef long long ll;
int n,m;
inline int read()
{
char c;
bool pd=0;
while((c=getchar())>'9'||c<'0')
if(c=='-') pd=1;
int res=c-'0';
while((c=getchar())>='0'&&c<='9')
res=(res<<3)+(res<<1)+c-'0';
return pd?-res:res;
}
const int N=210000;
int lc[N],rc[N],fa[N],mul[N],muls[N],tag[N],val[N];
ll sum[N];
inline void updata(const int &x)
{
muls[x]=muls[lc[x]]+muls[rc[x]]+mul[x];
sum[x]=val[x]+sum[lc[x]]+sum[rc[x]];
}
inline void tag_add(const int &x,const int &y)
{
if(!x) return;
sum[x]+=(ll)muls[x]*y;
val[x]+=mul[x]>0?y:-y;
tag[x]+=y;
}
inline void tag_down(const int &x)
{
if(tag[x])
{
tag_add(lc[x],tag[x]);
tag_add(rc[x],tag[x]);
tag[x]=0;
}
}
inline void rotate(const int &x)
{
int y=fa[x],z=fa[y];
int b=lc[y]==x?rc[x]:lc[x];
if(b) fa[b]=y;
fa[y]=x;fa[x]=z;
if(z)
{
if(lc[z]==y) lc[z]=x;
else rc[z]=x;
}
if(lc[y]==x) lc[y]=b,rc[x]=y;
else rc[y]=b,lc[x]=y;
updata(y);
}
int sta[N],rt;
inline void simplex(const int &x,const int &f)
{
if(x!=f) simplex(fa[x],f);
tag_down(x);
}
inline void splay(int x,const int &f)
{
sta[sta[0]=1]=x;
for(int y=x;y!=f;y=fa[y]) sta[++sta[0]]=fa[y];
while(sta[0]) tag_down(sta[sta[0]--]);
// simplex(x,f);
while(fa[x]!=f)
{
if(fa[fa[x]]!=f)
{
if((lc[fa[fa[x]]]==fa[x])==(lc[fa[x]]==x)) rotate(fa[x]);
else rotate(x);
}
rotate(x);
}
updata(x);
if(!fa[x]) rt=x;
}
int tot,fir[N],nex[N],go[N];
inline void add(const int &x,const int &y)
{
nex[++tot]=fir[x];fir[x]=tot;go[tot]=y;
nex[++tot]=fir[y];fir[y]=tot;go[tot]=x;
}
int q[N];
inline void dfs(const int &u,const int &f)
{
q[++q[0]]=2*u-1;
int e,v;
for(e=fir[u];v=go[e],e;e=nex[e])
if(v!=f) dfs(v,u);
q[++q[0]]=2*u;
}
inline void build(int &k,const int &l,const int &r)
{
if(l>r) return;
int mid=l+r>>1;
k=q[mid];
build(lc[k],l,mid-1);
build(rc[k],mid+1,r);
if(lc[k]) fa[lc[k]]=k;
if(rc[k]) fa[rc[k]]=k;
updata(k);
}
char sr[5];
inline int find_nex(const int &x)
{
splay(x,0);
int y=rc[x];
while(lc[y]) y=lc[y];
return y;
}
inline int find_pre(const int &x)
{
splay(x,0);
int y=lc[x];
while(rc[y]) y=rc[y];
return y;
}
int main()
{
// freopen("3786.in","r",stdin);
// freopen(".out","w",stdout);
srand(19260817);
n=read();
for(int i=2;i<=n;++i) add(read(),i);
q[++q[0]]=2*n+1;
dfs(1,0);
q[++q[0]]=2*n+2;
for(int i=1;i<=n;++i) mul[(i<<1)-1]=1,mul[i<<1]=-1;
for(int i=1;i<=n;++i)
{
val[(i<<1)-1]=val[i<<1]=read();
val[i<<1]*=-1;
}
build(rt,1,q[0]);
m=read();
int x,y,z,l,r;
while(m--)
{
scanf("%s",sr+1);
x=read();
// splay((rand()%(2*n+2))+1,0);
if(sr[1]=='Q')
{
r=find_nex((x<<1)-1);
splay(r,0);
printf("%lld\n",sum[lc[r]]);
}
if(sr[1]=='C')
{
y=read();
l=find_pre((x<<1)-1);
r=find_nex(x<<1);
splay(l,0);
splay(r,l);
z=lc[r];
lc[r]=0;
splay(r,0);
r=find_nex((y<<1)-1);
// splay((y<<1)-1,0);
splay(r,(y<<1)-1);
lc[r]=z;
fa[z]=r;
splay(z,0);
}
if(sr[1]=='F')
{
y=read();
l=find_pre((x<<1)-1);
r=find_nex(x<<1);
splay(l,0);
splay(r,l);
tag_add(lc[r],y);
splay(lc[r],0);
}
}
}
手动updata版本
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cmath>
using namespace std;
typedef long long ll;
int n,m;
inline int read()
{
char c;
bool pd=0;
while((c=getchar())>'9'||c<'0')
if(c=='-') pd=1;
int res=c-'0';
while((c=getchar())>='0'&&c<='9')
res=(res<<3)+(res<<1)+c-'0';
return pd?-res:res;
}
const int N=210000;
int lc[N],rc[N],fa[N],mul[N],muls[N],tag[N],val[N];
ll sum[N];
inline void updata(const int &x)
{
muls[x]=muls[lc[x]]+muls[rc[x]]+mul[x];
sum[x]=val[x]+sum[lc[x]]+sum[rc[x]];
}
inline void tag_add(const int &x,const int &y)
{
if(!x) return;
sum[x]+=(ll)muls[x]*y;
val[x]+=mul[x]>0?y:-y;
tag[x]+=y;
}
inline void tag_down(const int &x)
{
if(tag[x])
{
tag_add(lc[x],tag[x]);
tag_add(rc[x],tag[x]);
tag[x]=0;
}
}
inline void rotate(const int &x)
{
int y=fa[x],z=fa[y];
int b=lc[y]==x?rc[x]:lc[x];
if(b) fa[b]=y;
fa[y]=x;fa[x]=z;
if(z)
{
if(lc[z]==y) lc[z]=x;
else rc[z]=x;
}
if(lc[y]==x) lc[y]=b,rc[x]=y;
else rc[y]=b,lc[x]=y;
updata(y);
}
int sta[N],rt;
inline void simplex(const int &x,const int &f)
{
if(x!=f) simplex(fa[x],f);
tag_down(x);
}
inline void splay(int x,const int &f)
{
sta[sta[0]=1]=x;
for(int y=x;y!=f;y=fa[y]) sta[++sta[0]]=fa[y];
while(sta[0]) tag_down(sta[sta[0]--]);
// simplex(x,f);
while(fa[x]!=f)
{
if(fa[fa[x]]!=f)
{
if((lc[fa[fa[x]]]==fa[x])==(lc[fa[x]]==x)) rotate(fa[x]);
else rotate(x);
}
rotate(x);
}
updata(x);
if(!fa[x]) rt=x;
}
int tot,fir[N],nex[N],go[N];
inline void add(const int &x,const int &y)
{
nex[++tot]=fir[x];fir[x]=tot;go[tot]=y;
nex[++tot]=fir[y];fir[y]=tot;go[tot]=x;
}
int q[N];
inline void dfs(const int &u,const int &f)
{
q[++q[0]]=2*u-1;
int e,v;
for(e=fir[u];v=go[e],e;e=nex[e])
if(v!=f) dfs(v,u);
q[++q[0]]=2*u;
}
inline void build(int &k,const int &l,const int &r)
{
if(l>r) return;
int mid=l+r>>1;
k=q[mid];
build(lc[k],l,mid-1);
build(rc[k],mid+1,r);
if(lc[k]) fa[lc[k]]=k;
if(rc[k]) fa[rc[k]]=k;
updata(k);
}
char sr[5];
inline int find_nex(const int &x)
{
splay(x,0);
int y=rc[x];
while(lc[y]) y=lc[y];
return y;
}
inline int find_pre(const int &x)
{
splay(x,0);
int y=lc[x];
while(rc[y]) y=rc[y];
return y;
}
int main()
{
// freopen("3786.in","r",stdin);
// freopen(".out","w",stdout);
srand(19260817);
n=read();
for(int i=2;i<=n;++i) add(read(),i);
q[++q[0]]=2*n+1;
dfs(1,0);
q[++q[0]]=2*n+2;
for(int i=1;i<=n;++i) mul[(i<<1)-1]=1,mul[i<<1]=-1;
for(int i=1;i<=n;++i)
{
val[(i<<1)-1]=val[i<<1]=read();
val[i<<1]*=-1;
}
build(rt,1,q[0]);
m=read();
int x,y,z,l,r;
while(m--)
{
scanf("%s",sr+1);
x=read();
if(sr[1]=='Q')
{
r=find_nex((x<<1)-1);
splay(r,0);
printf("%lld\n",sum[lc[r]]);
}
if(sr[1]=='C')
{
y=read();
l=find_pre((x<<1)-1);
r=find_nex(x<<1);
splay(l,0);
splay(r,l);
z=lc[r];
lc[r]=0;
updata(r);updata(l);
r=find_nex((y<<1)-1);
splay(r,(y<<1)-1);
lc[r]=z;
fa[z]=r;
updata(r);
updata((y<<1)-1);
}
if(sr[1]=='F')
{
y=read();
splay((x<<1)-1,0);
splay(x<<1,(x<<1)-1);
z=rc[rt];
val[rt]+=mul[rt]*y;
val[z]+=mul[z]*y;
tag_add(lc[z],y);
updata(z);updata(rt);
}
}
}