题解:
这道题用二次剩余或者矩阵都可以做。
相当于链剖之后维护一个区间加等比数列的可持久化线段树。 因为比相同,所以很好维护。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
const int N=2e5+50, mod=1e9+9, base=383008016;
inline int add(int x,int y) {return (x+y>=mod) ? (x+y-mod) : (x+y);}
inline int dec(int x,int y) {return (x-y<0) ? (x-y+mod) : (x-y);}
inline int mul(int x,int y) {return (LL)x*y%mod;}
inline int power(int a,int b,int rs=1) {for(;b;b>>=1,a=mul(a,a)) if(b&1) rs=mul(rs,a); return rs;}
inline int inv(int a) {return power(a,mod-2);}
const int base1=mul(base+1,inv(2)), base2=mul(dec(1,base),inv(2)), iv1=inv(base1), iv2=inv(base2), iv=inv(base);
int n,m,ind,lastans,pw1[N],pw2[N];
int fa[N],dep[N],sze[N],son[N],top[N],dfn[N];
vector <int> edge[N];
struct ST {
int bs,s[N],pw[N];
int rt[N],lc[N*100],rc[N*100],sum[N*100],d[N*100],tot;
inline void build(int &k,int l,int r) {
k=++tot; if(l==r) return;
int mid=(l+r)>>1;
build(lc[k],l,mid);
build(rc[k],mid+1,r);
}
inline void upt(int k,int len) {
sum[k]=add(sum[lc[k]],sum[rc[k]]);
sum[k]=add(sum[k],mul(dec(s[len],1),d[k]));
}
inline void copy(int &x,int y) {x=++tot; d[x]=d[y]; sum[x]=sum[y]; lc[x]=lc[y]; rc[x]=rc[y];}
inline void inc(int &k,int l,int r,int L,int R,int v) {
copy(k,k);
if(L==l && r==R) {d[k]=add(d[k],v); upt(k,r-l+1); return;}
int mid=(l+r)>>1;
if(R<=mid) inc(lc[k],l,mid,L,R,v);
else if(L>mid) inc(rc[k],mid+1,r,L,R,v);
else inc(lc[k],l,mid,L,mid,v), inc(rc[k],mid+1,r,mid+1,R,mul(v,pw[mid+1-L]));
upt(k,r-l+1); return;
}
inline int ask(int &k,int l,int r,int L,int R) {
if(L==l && r==R) return sum[k];
int res=mul(d[k],dec(s[R-l+1],s[L-l]));
int mid=(l+r)>>1;
if(R<=mid) return add(res,ask(lc[k],l,mid,L,R));
else if(L>mid) return add(res,ask(rc[k],mid+1,r,L,R));
else return add(res,add(ask(lc[k],l,mid,L,mid),ask(rc[k],mid+1,r,mid+1,R)));
}
inline void init() {
pw[0]=s[0]=1;
for(int i=1;i<=n+1;i++) s[i]=mul(s[i-1],bs), ++s[i], pw[i]=mul(pw[i-1],bs);
build(rt[0],1,n);
}
} st[4];
inline int lca(int x,int y) {
while(top[x]^top[y])
(dep[top[x]]>dep[top[y]]) ? (x=fa[top[x]]) : (y=fa[top[y]]);
return (dep[x]>dep[y]) ? y : x;
}
inline void dfs(int x,int f) {
sze[x]=1; dep[x]=dep[f]+1; fa[x]=f;
for(auto v:edge[x]) if(v^f) {
dfs(v,x); sze[x]+=sze[v];
if(sze[son[x]]<sze[v]) son[x]=v;
}
}
inline void dfs_top(int x,int f) {
dfn[x]=++ind;
if(son[x]) top[son[x]]=top[x], dfs_top(son[x],x);
for(auto v:edge[x]) if(v^f && v^son[x]) top[v]=v, dfs_top(v,x);
}
inline void init() {
n=rd(), m=rd();
st[0].bs=inv(base1);
st[1].bs=inv(base2);
st[2].bs=base1;
st[3].bs=base2;
for(int i=0;i<=3;i++) st[i].init();
for(int i=1;i<n;i++) {
int x=rd(), y=rd();
edge[x].push_back(y);
edge[y].push_back(x);
} dfs(1,0); top[1]=1; dfs_top(1,0);
pw1[0]=1; for(int i=1;i<=n+1;i++) pw1[i]=mul(pw1[i-1],base1);
pw2[0]=1; for(int i=1;i<=n+1;i++) pw2[i]=mul(pw2[i-1],base2);
}
int tim;
inline int ask(int l,int r) {
int ans=0;
ans=add(ans,st[0].ask(st[0].rt[tim],1,n,l,r));
ans=dec(ans,st[1].ask(st[1].rt[tim],1,n,l,r));
ans=add(ans,st[2].ask(st[2].rt[tim],1,n,l,r));
ans=dec(ans,st[3].ask(st[3].rt[tim],1,n,l,r));
return ans;
}
int main() {
init();
for(int i=1;i<=m;i++) {
tim=i;
char ch=nc(); while(!isalpha(ch)) ch=nc();
if(ch=='A') {
for(int j=0;j<=3;j++) st[j].rt[i]=st[j].rt[i-1];
int x=rd()^lastans, y=rd(), l=lca(x,y);
int u=x, det=0;
while(dep[u]>=dep[l]) {
int f=top[u]; if(dep[f]<dep[l]) f=l;
det+=dep[u]-dep[f]+1;
st[0].inc(st[0].rt[i],1,n,dfn[f],dfn[u],pw1[det+1]);
st[1].inc(st[1].rt[i],1,n,dfn[f],dfn[u],pw2[det+1]);
u=fa[f];
}
u=y;
while(dep[u]>=dep[l]) {
int f=top[u]; if(dep[f]<dep[l]) f=l;
int kth=det+dep[f]-dep[l];
st[2].inc(st[2].rt[i],1,n,dfn[f],dfn[u],pw1[kth-1]);
st[3].inc(st[3].rt[i],1,n,dfn[f],dfn[u],pw2[kth-1]);
u=fa[f];
}
st[2].inc(st[2].rt[i],1,n,dfn[l],dfn[l],mod-pw1[det-1]);
st[3].inc(st[3].rt[i],1,n,dfn[l],dfn[l],mod-pw2[det-1]);
} else if(ch=='R') {
int x=rd()^lastans;
for(int j=0;j<=3;j++) st[j].rt[i]=st[j].rt[x];
} else if(nc()=='S') {
for(int j=0;j<=3;j++) st[j].rt[i]=st[j].rt[i-1];
int x=rd()^lastans, y=rd(), ans=0; swap(x,y);
if(x==y) ans=ask(1,n);
else if(!(dfn[y]>dfn[x] && dfn[y]<dfn[x]+sze[x])) ans=ask(dfn[x],dfn[x]+sze[x]-1);
else {
int last=y;
while(top[y]^top[x]) last=top[y], y=fa[top[y]];
y=(y!=x) ? son[x] : last;
ans=dec(ask(1,n),ask(dfn[y],dfn[y]+sze[y]-1));
} printf("%d\n",lastans=mul(ans,iv));
} else {
for(int j=0;j<=3;j++) st[j].rt[i]=st[j].rt[i-1];
int x=rd()^lastans, y=rd(), l=lca(x,y);
int u=x, ans=0;
while(dep[u]>=dep[l]) {
int f=top[u]; if(dep[f]<dep[l]) f=l;
ans=add(ans,ask(dfn[f],dfn[u]));
u=fa[f];
}
u=y;
while(dep[u]>=dep[l]) {
int f=top[u]; if(dep[f]<dep[l]) f=l;
ans=add(ans,ask(dfn[f],dfn[u]));
u=fa[f];
} ans=dec(ans,ask(dfn[l],dfn[l]));
printf("%d\n",lastans=mul(ans,iv));
}
}
}