Description
Input
第一行有一个整数 N,表示 S 国城市的数量。
接下来有 N-1 行,每行两个数 u,v 表示一条道路。
第 N+1 行为一个整数 Q,表示接下来有 Q 个操作。
接下来有 Q 行,每行表示一个操作,格式如题目描述所示。
Output
对于每一个 QUERY 操作,输出一个数,表示询问的当前编号为 X 和编号为 Y 的城市的最短路径间的城市 (包括编号为 X 的城市和编号为 Y 的城市)的士兵总和。
Sample Input
Sample Input1:
5
1 2
1 3
3 4
3 5
6
ADD 1 5 2
ADD 3 4 1
QUERY 1 4
SHIFT 1 4
ADD 5 4 1
QUERY 4 5
Sample Input12:
5
1 2
2 3
3 4
4 5
5
ADD 1 3 2
ADD 3 5 1
SHIFT 2 4
QUERY 1 3
QUERY 1 5
Sample Output
Sample Output1:
6
10
Sample Output2:
5
9
Data Constraint
Solution
-
刚了这么久终于过了……
-
还是套路,一棵形态LCT,维护的是当前树的形态;
-
一个权值LCT(Splay),维护的是当前形态下形态LCT中每个点对应的权值。
-
按要求操作即可,时间复杂度 O ( n l o g n ) O(n\ log\ n) O(n log n)。
Code
#include<cstdio>
#include<algorithm>
#include<cctype>
using namespace std;
typedef long long LL;
const int N=1e5+5;
int tot,top;
int first[N],nex[N<<1],en[N<<1];
int st[N];
char ty[7];
struct value
{
int fa[N],s[N][2],size[N];
LL key[N],sum[N],tag[N];
bool rev[N];
inline bool pd(int x)
{
return x==s[fa[x]][1];
}
inline void update(int x)
{
size[x]=size[s[x][0]]+size[s[x][1]]+1;
sum[x]=sum[s[x][0]]+sum[s[x][1]]+key[x];
}
inline void reverse(int x)
{
if(x) swap(s[x][0],s[x][1]),rev[x]^=1;
}
inline void modify(int x,LL val)
{
if(x)
{
sum[x]+=size[x]*val;
key[x]+=val;
tag[x]+=val;
}
}
inline void down(int x)
{
if(rev[x])
{
rev[x]=false;
reverse(s[x][0]);
reverse(s[x][1]);
}
if(tag[x])
{
modify(s[x][0],tag[x]);
modify(s[x][1],tag[x]);
tag[x]=0;
}
}
inline void rotate(int x)
{
down(x);
int y=fa[x],w=pd(x);
if(fa[x]=fa[y]) s[fa[y]][pd(y)]=x;
if(s[y][w]=s[x][w^1]) fa[s[y][w]]=y;
s[fa[y]=x][w^1]=y;
update(y);
}
inline void splay(int x)
{
for(int y;y=fa[x];rotate(x))
if(fa[y]) rotate(pd(x)==pd(y)?y:x);
update(x);
}
inline int root(int x)
{
while(fa[x]) x=fa[x];
return x;
}
int kth(int x,int k)
{
down(x);
if(size[s[x][0]]+1==k) return x;
if(size[s[x][0]]+1>k) return kth(s[x][0],k);
return kth(s[x][1],k-size[s[x][0]]-1);
}
}v;
struct shape
{
int fa[N],s[N][2],size[N],rt[N];
bool rev[N];
inline bool pd(int x)
{
return x==s[fa[x]][1];
}
inline bool isroot(int x)
{
return s[fa[x]][0]^x && s[fa[x]][1]^x;
}
inline void reverse(int x)
{
if(x) swap(s[x][0],s[x][1]),rev[x]^=1;
}
inline void update(int x)
{
size[x]=size[s[x][0]]+size[s[x][1]]+1;
}
inline void down(int x)
{
if(rev[x])
{
rev[x]=false;
reverse(s[x][0]);
reverse(s[x][1]);
}
}
inline void rotate(int x)
{
int y=fa[x],w=pd(x);
if((fa[x]=fa[y]) && !isroot(y)) s[fa[y]][pd(y)]=x;
if(s[y][w]=s[x][w^1]) fa[s[y][w]]=y;
s[fa[y]=x][w^1]=y;
rt[x]=rt[y],rt[y]=0;
update(y);
}
inline void splay(int x)
{
for(int y=st[top=1]=x;!isroot(y);y=fa[y]) st[++top]=fa[y];
while(top) down(st[top--]);
for(int y;!isroot(x);rotate(x))
if(!isroot(y=fa[x])) rotate(pd(x)==pd(y)?y:x);
update(x);
}
inline void access(int x)
{
for(int y=0;x;x=fa[y=x])
{
splay(x);
int xx=v.root(rt[x]);
xx=v.kth(xx,size[s[x][0]]+1);
v.splay(rt[x]=xx);
if(s[x][1])
{
rt[s[x][1]]=v.s[xx][1];
v.fa[v.s[xx][1]]=0;
v.s[xx][1]=s[x][1]=0;
}
if(y)
{
s[x][1]=y;
v.s[xx][1]=v.root(rt[y]);
if(v.s[xx][1]) v.fa[v.s[xx][1]]=xx;
}
v.update(xx);
update(x);
}
}
inline void mkroot(int x)
{
access(x),splay(x),reverse(x);
int xx=v.root(rt[x]);
xx=v.kth(xx,size[s[x][0]]+1);
v.splay(xx);
v.reverse(xx);
}
}s;
inline int read()
{
int X=0,w=0; char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
return w?-X:X;
}
inline void insert(int x,int y)
{
nex[++tot]=first[x];
first[x]=tot;
en[tot]=y;
}
void dfs(int x,int y)
{
s.fa[x]=y;
s.size[x]=v.size[x]=1;
s.rt[x]=x;
for(int i=first[x];i;i=nex[i])
if(en[i]^y) dfs(en[i],x);
}
int main()
{
freopen("shift.in","r",stdin);
freopen("shift.out","w",stdout);
int n=read();
for(int i=1;i<n;i++)
{
int x=read(),y=read();
insert(x,y);
insert(y,x);
}
dfs(1,0);
int q=read();
while(q--)
{
scanf("%s",&ty);
int x=read(),y=read();
if(ty[0]=='S' && x==y) continue;
s.mkroot(x);
s.access(y);
s.splay(y);
int yy=s.rt[y];
v.splay(yy);
yy=v.kth(yy,s.size[s.s[y][0]]+1);
v.splay(yy);
if(ty[0]=='A')
{
int z=read();
v.modify(yy,z);
}else
if(ty[0]=='S')
{
int pos=v.s[yy][0];
v.s[yy][0]=0;
v.fa[pos]=0;
pos=v.kth(pos,1);
v.splay(pos);
v.fa[pos]=yy;
v.s[yy][1]=pos;
v.update(yy);
}else
printf("%lld\n",v.sum[yy]);
}
return 0;
}