传送门
这篇博客主要是因为洛谷有毒瘤造了毒瘤数据卡树剖,所以只有全局平衡二叉树能过(而且代码还比树剖短。。。)并不想写题解,可以自己去洛谷题解区看。
update:
洛谷提交记录rank1是一个LCT?全局平衡二叉树没有LCT快?这什么鬼数据?
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define gc get_char
#define cs const
namespace IO{
cs int Rlen=1<<22|1;
char buf[Rlen],*p1,*p2;
inline char get_char(){return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;}
inline char peek(){return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1;}
inline char get_alpha(){while(!isalpha(peek()))++p1;return *p1++;}
template<typename T>
inline T get(){
char c;
while(!isdigit(c=gc()));T num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
inline int getint(){return get<int>();}
}
using namespace IO;
using std::cerr;
using std::cout;
cs int mod=1e4+7;
inline int add(int a,int b){return (a+=b)>=mod?a-mod:a;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){static ll r;r=(ll)a*b;return r>=mod?r%mod:r;}
inline int power(int a,int b,int res=1){
for(;b;b>>=1,a=mul(a,a))(b&1)&&(res=mul(res,a));
return res;
}
inline void Inc(int &a,int b){(a+=b)>=mod&&(a-=mod);}
inline void Dec(int &a,int b){(a-=b)<0&&(a+=mod);}
inline void Mul(int &a,int b){a=mul(a,b);}
int inv[mod];
inline void init_inv(){
inv[0]=inv[1]=1;
for(int re i=2;i<mod;++i)inv[i]=mul(inv[mod%i],mod-mod/i);
}
struct tag{
int x,y;
tag():x(1),y(0){}
void operator=(int v){v?(x=v,y=0):(x=y=1);}
void operator*=(int v){v?x=mul(x,v):++y;}
void operator/=(int v){v?x=mul(x,inv[v]):--y;}
operator int(){return y?0:x;}
};
cs int N=3e4+7,M=129;
int n,S,invS,Q;
struct atom{
int a[M],b[M],c[M],d[M];
atom(){}
void operator=(cs atom &n){
memcpy(a,n.a,sizeof(int)*S);
memcpy(b,n.b,sizeof(int)*S);
memcpy(c,n.c,sizeof(int)*S);
memcpy(d,n.d,sizeof(int)*S);
}
};
inline void merge(atom &C,cs atom &A,cs atom &B){
for(int re i=0;i<S;++i){
C.d[i]=add(add(A.d[i],B.d[i]),mul(A.c[i],B.b[i]));
C.c[i]=add(mul(B.a[i],A.c[i]),B.c[i]);
C.b[i]=add(mul(A.a[i],B.b[i]),A.b[i]);
C.a[i]=mul(A.a[i],B.a[i]);
}
}
inline void FWT(int *A){
for(int re i=1;i<S;i<<=1)
for(int re j=0;j<S;j+=i<<1)
for(int re k=0;k<i;++k){
int x=A[j|k],y=A[i|j|k];
A[j|k]=add(x,y),A[i|j|k]=dec(x,y);
}
}
inline void IFWT(int *A){FWT(A);for(int re i=0;i<S;++i)Mul(A[i],invS);}
int nxt[N<<1],to[N<<1],last[N],ecnt;
inline void addedge(int u,int v){
nxt[++ecnt]=last[u],last[u]=ecnt,to[ecnt]=v;
nxt[++ecnt]=last[v],last[v]=ecnt,to[ecnt]=u;
}
int siz[N],son[N];
void pre_dfs(int u,int p){
siz[u]=1;
for(int re e=last[u],v=to[e];e;v=to[e=nxt[e]])if(v!=p){
pre_dfs(v,u),siz[u]+=siz[v];
if(siz[v]>siz[son[u]])son[u]=v;
}
}
int val[N],fw[M][M],ans[M];
namespace GBT{
int rt;
int son[N][2],fa[N],lsiz[N];
int st[N],top;
atom w[N],a[N];
tag LF[N][M];int LH[N][M];
inline void init_node(int u){
int *w=fw[val[u]];atom &a=GBT::w[u];
for(int re i=0;i<S;++i){
a.a[i]=mul(LF[u][i],w[i]);
a.d[i]=add(a.a[i],LH[u][i]);
}
memcpy(a.b,a.a,sizeof(int)*S);
memcpy(a.c,a.a,sizeof(int)*S);
}
inline void pushup(int u){
merge(a[u],a[son[u][0]],w[u]);
merge(a[u],a[u],a[son[u][1]]);
}
inline void ins(int u,int v){
int *t1=a[v].c,*t2=a[v].d;
for(int re i=0;i<S;++i){
LF[u][i]*=add(t1[i],1);
Inc(LH[u][i],t2[i]);
}
}
inline void del(int u,int v){
int *t1=a[v].c,*t2=a[v].d;
for(int re i=0;i<S;++i){
LF[u][i]/=add(t1[i],1);
Dec(LH[u][i],t2[i]);
}
}
inline int subbuild(int l,int r){
if(l==r){pushup(st[l]);return st[l];}if(l>r)return 0;
int tot=0;for(int re i=l;i<=r;++i)tot+=lsiz[st[i]];
for(int re i=l,now=lsiz[st[i]];i<=r;now+=lsiz[st[++i]])
if(now*2>=tot){
son[st[i]][0]=subbuild(l,i-1),son[st[i]][1]=subbuild(i+1,r);
fa[son[st[i]][0]]=fa[son[st[i]][1]]=st[i];pushup(st[i]);
return st[i];
}
cerr<<"error 1\n";
abort();
}
inline int build(int u){
for(int re p=u;p;p=::son[p])lsiz[p]=siz[p]-siz[::son[p]];
for(int re p=u;p;p=::son[p])
for(int re e=last[p],v=to[e];e;v=to[e=nxt[e]])if(!lsiz[v]){
v=build(v);fa[v]=p;ins(p,v);
}top=0;
for(int re p=u;p;p=::son[p])st[++top]=p,init_node(p);
std::reverse(st+1,st+top+1);return subbuild(1,top);
}
bool got;
inline void get_ans(){
// cerr<<"get_ans \n";
if(got)return ;got=true;
memcpy(ans,a[rt].d,sizeof(int)*S);
IFWT(ans);
}
inline bool isroot(int u){return son[fa[u]][1]!=u&&son[fa[u]][0]!=u;}
inline void modify(){got=false;
int u=getint();
val[u]=getint();init_node(u);
while(u){
if(isroot(u)&&fa[u]){
del(fa[u],u);
pushup(u);
ins(fa[u],u);
init_node(fa[u]);
}
else pushup(u);
u=fa[u];
}
}
inline void init(){
for(int re i=1;i<=n;++i)
for(int re j=0;j<S;++j)LF[i][j]=1;
std::fill(w->a,w->a+S,1);
std::fill(a->a,a->a+S,1);
rt=build(1);
}
}
signed main(){
#ifdef zxyoi
freopen("cut.in","r",stdin);
#endif
init_inv();n=getint(),invS=inv[S=getint()];
for(int re i=1;i<=n;++i)val[i]=getint();
for(int re i=1;i<n;++i)addedge(getint(),getint());
for(int re i=0;i<M;++i)fw[i][i]=1,FWT(fw[i]);
pre_dfs(1,0);GBT::init();
Q=getint();
while(Q--){
switch(get_alpha()){
case 'Q':GBT::get_ans();cout<<ans[getint()]<<"\n";break;
case 'C':GBT::modify();
}
}
return 0;
}