6687. 2020.06.04省选模拟树没了(tree)

Posted gmh77

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了6687. 2020.06.04省选模拟树没了(tree)相关的知识,希望对你有一定的参考价值。

题目描述

技术图片
技术图片

题解

LCT复习

把颜色挂在边上,给点1建一个父亲,对每一种颜色维护森林,每棵树的根不是该颜色,维护虚边的答案和

询问的话直接找一棵树的根,然后makeroot+access即可得到答案

需要维护子树+虚边size,直接相连的虚边size以及虚边的答案

每次修改就先把原来的答案减掉再加新的答案,操作后要把树的根makeroot

其他注意事项见https://www.cnblogs.com/gmh77/p/13055965.html

code

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define N 2000000
#define mod 1000000007
#define ll long long
#define file
using namespace std;

int a[400001][2],ls[200001],Fa[200001],c[200001],n,Q,K,i,j,k,l,Len,len,x,y;
int tr[N+1][2],fa[N+1],size[N+1],size2[N+1]; //size=子树+轻边大小 size2=直接相连的虚边size sum=直接相连的虚边答案
ll p[200001],ans[200001],sum[N+1];
bool rev[N+1],rt[N+1];
map<int,int> hs[200001];
map<int,int> :: iterator I;
char ch;

ll qpower(ll a,int b) {ll ans=1; while (b) {if (b&1) ans=ans*a%mod;a=a*a%mod;b>>=1;} return ans;}
void NEW(int x,int y) {++Len;a[Len][0]=y;a[Len][1]=ls[x];ls[x]=Len;}
void bfs()
{
	int d[200001],i,j,k,l,h,t;
	bool bz[200001];
	memset(bz,0,sizeof(bz));
	
	h=0;t=1;d[1]=1;bz[1]=1;
	while (h<t)
	{
		for (i=ls[d[++h]]; i; i=a[i][1])
		if (!bz[a[i][0]])
		{
			bz[a[i][0]]=1;
			d[++t]=a[i][0];
			Fa[a[i][0]]=d[h];
		}
	}
}

int get(int c,int t) {I=hs[c].find(t);if (I!=hs[c].end()) return I->second; hs[c][t]=++len;size[len]=1;rt[len]=1; return len;}
void swap(int &x,int &y) {int z=x;x=y;y=z;}
void up(int t) {size[t]=size[tr[t][0]]+size[tr[t][1]]+1+size2[t];}
void down(int t) {if (rev[t]) swap(tr[t][0],tr[t][1]),rev[t]=0,rev[tr[t][0]]^=1,rev[tr[t][1]]^=1;}
void rot(int t)
{
	int Fa=fa[t],Fa2=fa[Fa],x=tr[Fa][1]==t,x2=tr[Fa2][1]==Fa,son=tr[t][x^1];
	
	fa[t]=Fa2,fa[Fa]=t,fa[son]=Fa;
	if (!rt[Fa]) tr[Fa2][x2]=t;//1
	tr[t][x^1]=Fa,tr[Fa][x]=son;
	up(Fa),up(t);
	
	if (rt[Fa]) rt[Fa]=0,rt[t]=1;
}
void splay(int t)
{
	int Fa,Fa2;
	down(t);
	while (!rt[t])
	{
		Fa=fa[t],Fa2=fa[Fa];
		if (!rt[Fa])
		{
			down(Fa2),down(Fa),down(t);
			if ((tr[Fa2][0]==Fa)^(tr[Fa][0]==t))
			rot(t),rot(t);
			else
			rot(Fa),rot(t);
		}
		else down(Fa),down(t),rot(t);
	}
}
void access(int t)
{
	int i,j,k,l,ls=0;
	
	while (t)
	{
		splay(t);
		sum[t]=(sum[t]+p[size[tr[t][1]]])%mod;
		size2[t]+=size[tr[t][1]];
		rt[tr[t][1]]=1;tr[t][1]=0;
		if (ls)
		{
			sum[t]=(sum[t]-p[size[ls]])%mod;
			size2[t]-=size[ls];
			tr[t][1]=ls;rt[ls]=0;
		}
		
		ls=t,t=fa[t];
	}
}
void mt(int t)
{
	access(t);
	splay(t);
	rev[t]^=1;
}
void link(int x,int y)
{
	mt(y);mt(x);
	size[x]+=size[y],size2[x]+=size[y],sum[x]=(sum[x]+p[size[y]])%mod;
	fa[y]=x;
}
void cut(int x,int y)
{
	mt(x);access(y);access(x);fa[y]=0;//2
	size[x]-=size[y],size2[x]-=size[y],sum[x]=(sum[x]-p[size[y]])%mod;
}
int gf(int t)
{
	while (fa[t]) t=fa[t];
	down(t);
	while (tr[t][0]) t=tr[t][0],down(t);
	return t;
}

int main()
{
	freopen("tree.in","r",stdin);
	#ifdef file
	freopen("tree.out","w",stdout);
	#endif
	
	scanf("%d%d%d",&n,&Q,&K);
	fo(i,1,n) scanf("%d",&c[i]),p[i]=qpower(i,K);
	fo(i,1,n-1) scanf("%d%d",&j,&k),NEW(j,k),NEW(k,j);
	
	bfs();len=0;
	fo(i,1,n)
	{
		j=get(c[i],Fa[i]);k=get(c[i],i);
		l=gf(j);access(l);ans[c[i]]=(ans[c[i]]-sum[l])%mod;
		link(j,k);
		mt(l);access(l);ans[c[i]]=(ans[c[i]]+sum[l])%mod;
	}
	
	for (;Q;--Q)
	{
		ch=getchar();
		while (ch!=‘Q‘ && ch!=‘M‘) ch=getchar();
		
		switch (ch)
		{
			case ‘M‘:{
				scanf("%d%d",&x,&y);
				j=get(c[x],Fa[x]);k=get(c[x],x);
				l=gf(j);access(l);ans[c[x]]=(ans[c[x]]-sum[l])%mod;
				cut(j,k);
				mt(l);access(l);ans[c[x]]=(ans[c[x]]+sum[l])%mod;
				mt(k);access(k);ans[c[x]]=(ans[c[x]]+sum[k])%mod;
				
				c[x]=y;
				j=get(c[x],Fa[x]);k=get(c[x],x);
				l=gf(j);access(l);ans[c[x]]=(ans[c[x]]-sum[l])%mod;
				mt(k);access(k);ans[c[x]]=(ans[c[x]]-sum[k])%mod;
				link(j,k);mt(l);access(l);ans[c[x]]=(ans[c[x]]+sum[l])%mod;
				break;
			}
			case ‘Q‘:{
				scanf("%d",&x);
				printf("%lld
",(ans[x]+mod)%mod);
				break;
			}
		}
	}
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}


以上是关于6687. 2020.06.04省选模拟树没了(tree)的主要内容,如果未能解决你的问题,请参考以下文章

6682. 2020.06.04省选模拟串在哪

6682. 2020.06.04省选模拟串在哪

[考试反思]0514省选模拟96:对比

[考试反思]0514省选模拟96:对比

[考试反思]0323省选模拟53:常数

6700. 2020.06.07省选模拟得分