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)的主要内容,如果未能解决你的问题,请参考以下文章