Solution
- 对于每个颜色建一棵 LCT
- 由于两点间至多有一条边,可用 map 维护两点间边的颜色
- 0 操作把每颗颜色的 LCT 上 x Splay 到 顶点,改颜色
- 1 操作先依次判断,再断原来的边,连边
- 2 操作在对应颜色的 LCT 内将 u 至 v 的路径提取出来,输出维护的最大值
Code
#include <cstdio>
#include <cstdlib>
#include <map>
#include <algorithm>
#define ll long long
using namespace std;
const int N=1e5+10;
int n,m,k,c,u,v,w,col[10010][11],opt;
int rev[N],ch[N][2],fa[N],val[N],ma[N],st[N];
map <ll,int> dict;
bool nroot(int x)
{
return x==ch[fa[x]][0]||x==ch[fa[x]][1];
}
int get(int x)
{
return x==ch[fa[x]][1];
}
void push_up(int x)
{
ma[x]=val[x];
if(ch[x][0]) ma[x]=max(ma[x],ma[ch[x][0]]);
if(ch[x][1]) ma[x]=max(ma[x],ma[ch[x][1]]);
}
void change(int x)
{
if(!x) return ;
swap(ch[x][0],ch[x][1]);
rev[x]^=1;
}
void push_down(int x)
{
if(!rev[x]) return ;
change(ch[x][0]),change(ch[x][1]);
rev[x]=0;
}
void rotate(int x)
{
int y=fa[x],z=fa[y],wh=get(x);
if(nroot(y)) ch[z][get(y)]=x;
if(ch[x][!wh]) fa[ch[x][!wh]]=y;
ch[y][wh]=ch[x][!wh];
ch[x][!wh]=y;
fa[y]=x,fa[x]=z;
push_up(y),push_up(x);
}
void splay(int x)
{
st[++st[0]]=x;
for(int i=x;nroot(i);i=fa[i]) st[++st[0]]=fa[i];
for(;st[0];st[0]--) push_down(st[st[0]]);
for(int fx;fx=fa[x],nroot(x);rotate(x))
if(nroot(fx)) rotate(get(x)==get(fx)?fx:x);
}
void access(int x)
{
for(int y=0;x;x=fa[y=x])
splay(x),ch[x][1]=y,push_up(x);
}
void makeroot(int x)
{
access(x);
splay(x);
change(x);
}
int findroot(int x)
{
access(x);
splay(x);
while(ch[x][0]) push_down(x),x=ch[x][0];
splay(x);
return x;
}
int link(int x,int y)
{
makeroot(x);
if(findroot(y)!=x) fa[x]=y;
else return 0;
return 1;
}
void cut(int x,int y)
{
makeroot(x);
if(findroot(y)==x && fa[y]==x && !ch[y][0])
fa[y]=ch[x][1]=0;
}
int split(int x,int y)
{
makeroot(x);
access(y);
splay(y);
return y;
}
int main()
{
scanf("%d%d%d%d",&n,&m,&c,&k);
for(int i=1;i<=n;i++)
{
scanf("%d",&val[i]);
for(int j=1;j<c;j++) val[j*n+i]=val[i];
}
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&u,&v,&w);
w++;
if(u>v) swap(u,v);
col[u][w]++,col[v][w]++;
link((w-1)*n+u,(w-1)*n+v);
ll x=u;
x*=n,x+=v;
dict[x]=w;
}
while(k--)
{
scanf("%d%d%d",&opt,&u,&v);
if(!opt)
{
for(int i=0;i<c;i++)
{
int x=i*n+u;
splay(x),val[x]=v,push_up(x);
}
continue;
}
scanf("%d",&w);
if(opt==1)
{
w++;
if(u>v) swap(u,v);
ll x=u;
x*=n,x+=v;
if(!dict.count(x))
{
puts("No such edge.");
continue;
}
if(dict[x]==w)
{
puts("Success.");
continue;
}
if(col[u][w]>1 || col[v][w]>1)
{
puts("Error 1.");
continue;
}
if(link(u+n*(w-1),v+n*(w-1))) col[u][w]++,col[v][w]++;
else
{
puts("Error 2.");
continue;
}
int pre=dict[x];
cut(u+n*(pre-1),v+n*(pre-1));
col[u][pre]--,col[v][pre]--;
dict[x]=w;
puts("Success.");
}
else
{
u++;
int x=v+n*(u-1),y=w+n*(u-1);
makeroot(x);
if(findroot(y)!=x) puts("-1");
else printf("%d\n",ma[split(x,y)]);
}
}
return 0;
}
来源:https://www.cnblogs.com/hsez-cyx/p/12393712.html