题目链接:星系探索
最近越来越懒了都不想写blog了QAQ
子树修改,链查询,树结构改变,单纯的lct已经不能满足这道题了QAQ
考虑dfs序,设每个点再dfs序中的位置为st[x],ed[x],我们在st[x]的位置上赋值为x的值,在ed[x]上赋值为-x的值,这样查询链的时候不在链上的点的贡献会被抵消
修改也很简单
至于改变父节点,只要把当前子树的那一段dfs序删去并加在新父节点的后面即可
然而这个代码在BZ上迷之RE在本地机上AC是什么鬼?
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=200051;
int n,m,a[maxn],fz[maxn],w[maxn],sta[maxn];
int st[maxn],ed[maxn],root,tot=0,h[maxn],ind=0;
struct edge{int to,next;}G[maxn];
struct Nodes{
int c[2],s0,s1,add,fa;
LL s;
};
struct splay_tree{
Nodes t[maxn];
void push_up(int x){
t[x].s0=t[t[x].c[0]].s0+t[t[x].c[1]].s0+(w[x]==1);
t[x].s1=t[t[x].c[0]].s1+t[t[x].c[1]].s1+(w[x]==-1);
t[x].s=t[t[x].c[0]].s+t[t[x].c[1]].s+fz[x];
}
void update(int x,int v){
if (!x) return;
t[x].s+=1LL*(t[x].s0-t[x].s1)*v;
fz[x]+=w[x]*v;
t[x].add+=v;
}
void push_down(int x){
if (!t[x].add||!x) return;
update(t[x].c[0],t[x].add);
update(t[x].c[1],t[x].add);
t[x].add=0;
}
void pre(int x){
int top=0;
for (;x;x=t[x].fa) sta[++top]=x;
while (top) push_down(sta[top--]);
}
void rotate(int p,int x){
int mark= p==t[x].c[1];
int y=t[p].c[mark^1],z=t[x].fa;
if (t[z].c[0]==x) t[z].c[0]=p;
if (t[z].c[1]==x) t[z].c[1]=p;
if (y) t[y].fa=x; t[x].c[mark]=y;
t[p].fa=z; t[p].c[mark^1]=x; t[x].fa=p;
push_up(x);
}
void splay(int p,int k){
pre(p);
while (t[p].fa!=k){
int x=t[p].fa,y=t[x].fa;
if (y==k) rotate(p,x);
else if (p==t[x].c[0]^x==t[y].c[0]) rotate(p,x),rotate(p,y);
else rotate(x,y),rotate(p,x);
} push_up(p);
if (!k) root=p; return;
}
int findmin(int x){
while (t[x].c[0]) x=t[x].c[0];
return x;
}
int findmax(int x){
while (t[x].c[1]) x=t[x].c[1];
return x;
}
void split(int x,int y){
splay(x,0);
int t1=findmax(t[x].c[0]);
splay(y,0);
int t2=findmin(t[y].c[1]);
splay(t1,0);
splay(t2,root);
}
void build(int l,int r,int fat){
if (l>r) return;
int mid=(l+r)>>1;
t[mid].fa=fat;
if (fat) t[fat].c[mid>fat]=mid;
if(l==r){t[l].s=fz[l];t[l].s0=w[l]==1;t[l].s1=1-t[l].s0;return;}
build(l,mid-1,mid); build(mid+1,r,mid);
push_up(mid);
}
void work1(){
int x; scanf("%d",&x);
splay(1,0); splay(st[x],root);
printf("%lld\n",t[t[t[root].c[1]].c[0]].s+fz[root]+fz[t[root].c[1]]);
}
void work2(){
int x,y; scanf("%d%d",&x,&y);
splay(st[x],0); splay(ed[x],root);
update(t[t[root].c[1]].c[0],y);
fz[root]+=w[root]*y;
fz[t[root].c[1]]+=w[t[root].c[1]]*y;
push_up(t[root].c[1]);
push_up(root);
}
void work3(){
int x,y; scanf("%d%d",&x,&y);
split(st[x],ed[x]);
int tmp=t[root].c[1],tmp2=t[tmp].c[0];
t[tmp].c[0]=0;
push_up(tmp); push_up(root);
splay(st[y],0);
splay(findmin(t[root].c[1]),root);
t[t[root].c[1]].c[0]=tmp2;
t[tmp2].fa=t[root].c[1];
push_up(t[root].c[1]); push_up(root);
}
}s;
void add(int x,int y){
G[++tot].to=y;G[tot].next=h[x];h[x]=tot;
}
void dfs(int x){
st[x]=++ind; fz[ind]=a[x]; w[ind]=1;
for (int i=h[x];i;i=G[i].next) if (!st[G[i].to]) dfs(G[i].to);
ed[x]=++ind; fz[ind]=-a[x]; w[ind]=-1;
}
int main(){
scanf("%d",&n);
for (int i=2;i<=n;++i){
int x; scanf("%d",&x);
add(x,i);
}
for (int i=1;i<=n;++i) scanf("%d",&a[i]);
ind=1;
dfs(1);
s.build(1,ind+1,0);
scanf("%d",&m);
for (int i=1;i<=m;++i){
char ch; cin>>ch;
if (ch=='Q') s.work1();
else if (ch=='F') s.work2();
else if (ch=='C') s.work3();
}
}