6687. 【JZOJ 省選模擬】樹沒了(tree)

題目

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);
		}
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章