题目
Description
Input
Output
2操作的个数行,每行代表一个询问的答案。
Sample Input
5 5 1
1 2 3 4 5
1 2
2 3
2 4
1 5
Q 1
M 4 1
Q 1
M 2 1
Q 1
Sample Output
1
2
3
Data Constraint
思路
考虑将点的颜色放到父亲的边上,再用LCT维护每一种颜色的联通块
总点数是O(n+q)级别的
一个同色联通块,对应树中一个联通块+非这个颜色的根
那么,LCT加边删边要维护影响到的联通块的大小。注意要预处理各个底数的k次幂
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+77,mod=1e9+7;
int n,q,k,x,y,ts,va[N],yjy[N],yjy2[N],fa[N],d[N];
ll ans[N];
char c;
vector<int>e[N];
map<int,int>pos[N];
struct tr
{
tr *f,*s[2];
ll sum;
int si,a;
bool is;
void up()
{
si=a+s[0]->si+s[1]->si;
}
void ro()
{
tr *y=f;int z=y->s[1]==this;
(y->s[z]=s[!z]) ->f=y;
f=y->f;y->is?f->s[y==f->s[1]]=this:0;
(s[!z]=y) ->f=this;y->up();swap(is,y->is);
}
void sp()
{
for(;is;ro() )
if(f->is)
(this==f->s[1]) ==(f==f->f->s[1]) ?f->ro() :ro();
up();
}
}t[N*4];
void ac(tr *x)
{
tr *xx=x,*y=t;
for(;x!=t;y=x,x=x->f)
{
x->sp();
x->sum+=va[x->s[1]->si]-va[y->si];
x->a+=x->s[1]->si-y->si;
x->s[1]->is=0;
(x->s[1]=y) ->is=1;
x->up();
}
xx->sp();
}
int power(int x,int y)
{
int t=1;
for(;y;y>>=1,x=(ll) x*x%mod) if(y&1) t=(ll) t*x%mod;
return t;
}
int get(int x,int c)
{
if(pos[c].count(x) ) return pos[c][x];
pos[c][x]=++ts;
t[ts].f=t[ts].s[0]=t[ts].s[1]=t;
t[ts].a=t[ts].si=1;
t[ts].sum=0;
return ts;
}
int find_root(tr *x)
{
tr *y;
for(y=x;y->s[0]!=t;) y=y->s[0];
y->sp();
return y-t;
}
void add(tr *x,tr *y)
{
x->sp();
y->sp();
x->f=y;
x->is=0;
y->a+=x->si;
y->sum+=va[x->si];
y->up();
}
void cut(tr *x,tr *y)
{
x->sp();
y->sp();
x->f=y->s[1]=t;
x->is=0;
y->up();
}
void del(int x,int c)
{
int px=get(x,c) ,py=get(fa[x],c) ,rt;
ac(t+px);
(ans[c]+=t[px].sum) %=mod;
rt=find_root(t+px);
(ans[c]-=va[t[rt].s[1]->si]) %=mod;
cut(t+px,t+py);
t[rt].sp();
(ans[c]+=va[t[rt].s[1]->si]) %=mod;
}
void ins(int x,int c)
{
int px=get(x,c) ,py=get(fa[x],c) ,rt;
ac(t+px);
(ans[c]-=t[px].sum) %=mod;
ac(t+py);
rt=find_root(t+py);
(ans[c]-=va[t[rt].s[1]->si]) %=mod;
add(t+px,t+py);
ac(t+px);
t[rt].sp();
(ans[c]+=va[t[rt].s[1]->si]) %=mod;
}
void ch(int x,int c)
{
if(c==yjy[x]) return;
if(yjy[x]) del(x,yjy[x]);
ins(x,c);
yjy[x]=c;
}
int main()
{
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
scanf("%d%d%d",&n,&q,&k);
for(int i=1; i<=n; i++) va[i]=power(i,k);
for(int i=1; i<=n; i++) scanf("%d",&yjy2[i]);
for(int i=2; i<=n; i++) scanf("%d%d",&x,&y) ,e[x].push_back(y) ,e[y].push_back(x);
fa[1]=n+1;
d[1]=1;
for(int l=0,r=1,x;x=d[++l],l<=r;)
for(int i:e[x]) if(i!=fa[x])
fa[i]=x,d[++r]=i;
for(int i=1; i<=n; i++) ch(i,yjy2[i]);
int qs=0;
for(int o=1; o<=q; o++)
{
scanf("\n");
c=getchar();
if(c=='M')
{
scanf("%d%d",&x,&y);
ch(x,y);
}
else
{
++qs;
scanf("%d",&x);
printf("%d\n",(ans[x]%mod+mod) %mod);
}
}
}