子树有关修改,显然不能用Link-Cut-Tree...
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<stack>
using namespace std;
inline int read()
{
int x=0; char ch=getchar();
while (ch<‘0‘ || ch>‘9‘) {ch=getchar();}
while (ch>=‘0‘ && ch<=‘9‘) {x=x*10+ch-‘0‘; ch=getchar();}
return x;
}
#define LL long long
#define MAXN 200010
int N,M,power[MAXN],val[MAXN];
struct EdgeNode{int next,to,d;}edge[MAXN<<1];
int head[MAXN],cnt=1;
inline void AddEdge(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;}
inline void InsertEdge(int u,int v) {AddEdge(u,v); AddEdge(v,u);}
int pl[MAXN],dfn,pr[MAXN],pre[MAXN],del[MAXN];
void DFS(int now,int last)
{
pl[now]=++dfn; pre[dfn]=now; del[dfn]=1;
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=last)
DFS(edge[i].to,now);
pr[now]=++dfn; del[dfn]=-1;
}
namespace SplayTree
{
int fa[MAXN],son[MAXN][2],sz,root,ln[MAXN],rn[MAXN],pos[MAXN];
LL sum[MAXN],tag[MAXN];
//ln记录左的数量,rn记录右的数量,tag标记
#define ls(x) son[x][0]
#define rs(x) son[x][1]
#define INF 1000100
inline void Update(int now)
{
sum[now]=sum[ls(now)]+sum[rs(now)]+(LL)val[now];
ln[now]=ln[ls(now)]+ln[rs(now)]+(del[now]==1);
rn[now]=rn[ls(now)]+rn[rs(now)]+(del[now]==-1);
}
inline void paint(int now,LL D) {if (now) val[now]+=D*del[now],sum[now]+=D*(ln[now]-rn[now]),tag[now]+=D;}
inline void PushDown(int now)
{
if (!tag[now]) return;
LL D=tag[now]; tag[now]=0;
if (ls(now)) paint(ls(now),D);
if (rs(now)) paint(rs(now),D);
}
void print(int now)
{
PushDown(now);
if (val[now]!=INF && val[now]!=-INF)
printf("ID=%d ---%d [%d %d] %d %I64d %d %d %d %I64d\n",
now,fa[now],ls(now),rs(now),val[now],sum[now],ln[now],rn[now],del[now],tag[now]);
if (son[now][0]) print(son[now][0]);
if (son[now][1]) print(son[now][1]);
}
inline bool Right(int now) {return son[fa[now]][1]==now;}
inline void rotate(int now)
{
PushDown(fa[now]); PushDown(now);
int f=fa[now],gf=fa[f],wh=Right(now);
son[f][wh]=son[now][wh^1]; fa[son[f][wh]]=f;
fa[f]=now; son[now][wh^1]=f; fa[now]=gf;
if (gf) son[gf][son[gf][1]==f]=now;
Update(f); Update(now);
}
inline void splay(int now,int tar)
{
for (int f; (f=fa[now])!=tar; rotate(now))
if (fa[f]!=tar) rotate(Right(now)==Right(f)? f:now);
if (!tar) root=now;
}
inline int fmin(int x) {while (son[x][0]) x=son[x][0]; return x;}
inline int fmax(int x) {while (son[x][1]) x=son[x][1]; return x;}
inline void Split(int l,int r)
{
splay(l,0); int x=fmax(ls(root));
splay(r,0); int y=fmin(rs(root));
splay(x,0); splay(y,x);
}
inline LL Query(int pos) {Split(pl[1],pl[pos]); return sum[ls(rs(root))];}
inline void Change(int x,int D)
{
Split(pl[x],pr[x]);
int rt=son[rs(root)][0];
sum[rt]+=(LL)(ln[rt]-rn[rt])*D; val[rt]+=D*del[rt]; tag[rt]+=D;
Update(rs(root)); Update(root);
}
inline void BuildTree(int l,int r,int last)
{
if (r<l) return;
int mid=(l+r)>>1,now=mid;
fa[now]=last; son[last][now>last]=now;
if (l==r)
{sum[now]=val[now]; ln[now]=del[now]==1; rn[now]=1-ln[now]; return;}
BuildTree(l,mid-1,now); BuildTree(mid+1,r,now);
Update(now);
}
inline void Init() {BuildTree(1,(N<<1)+2,0); root=(1+(N<<1)+2)>>1;}
inline void MakeRoot(int now,int father)
{
Split(pl[now],pr[now]);
int rt=ls(rs(root));
fa[ls(rs(root))]=0;
son[rs(root)][0]=0;
Update(rs(root)),Update(root);
splay(pl[father],0); splay(fmin(rs(root)),root);
son[rs(root)][0]=rt; fa[rt]=rs(root);
Update(rs(root)),Update(root);
}
}
using namespace SplayTree;
int main()
{
N=read();
for (int i=2; i<=N; i++) InsertEdge(i,read());
dfn=1; DFS(1,0);
for (int i=1; i<=N; i++) power[i]=read();
// for (int i=1; i<=N; i++) printf("id=%d [%d , %d]\n",pre[i],pl[pre[i]],pr[pre[i]]);
for (int i=1; i<=N; i++) val[pl[i]]+=power[i],val[pr[i]]-=power[i];
// for (int i=1; i<=dfn; i++) printf("%d ",val[i]); puts("");
M=read();
SplayTree::Init();
while (M--)
{
// print(root);
char opt[5]; scanf("%s",opt); int x,y;
if (opt[0]==‘Q‘) x=read(),printf("%I64d\n",SplayTree::Query(x));
if (opt[0]==‘C‘) x=read(),y=read(),SplayTree::MakeRoot(x,y);
if (opt[0]==‘F‘) x=read(),y=read(),SplayTree::Change(x,y);
}
return 0;
}
一天前..我:char哥,要是DFS序不用线段树,用Splay的话,不就可以支持子树交换XXX了吗... char哥:...woc!这么科学....
于是跟char哥连坐,写了一天Splay,然后这道题昨天没调出来...
终于写出来了...40s时限41s AC....
我:我一定要压到40s以内! ..... 我:当我没说;
我:char哥,你有什么压常数的技巧么? char哥:重写,你这程序已经没救了!......