题目描述:
LCT裸题...
(然后这个辣鸡就调了2H
题目分析:
基本思路同本题
我们同样也可以开11个颜色的LCT分别去维护联通关系
对于0操作,就直接对每个LCT的u权值更替即可
对于2操作,我们只需要在要查询的颜色的LCT查询 u v 路径最大值
只有1操作比较棘手
维护一个二维数组 d[x][c] 表示 x 点 的 c 颜色变有多少条
这样当我们新连边的时候,就可以判断条件1了
对于条件2 当 u v 本来就有边 而且在新的颜色里也联通 那么就出环了
这样就维护完了(大雾
题目链接:
Ac 代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
const int maxm=21000;
int d[maxm][20];
int val[maxm];
int n,m,c,q;
struct LCT{
int son[maxm][2],fa[maxm],rev[maxm],stk[maxm],max[maxm];
int top;
inline void pushup(int x)
{
max[x]=val[x];
if(son[x][0]) max[x]=std::max(max[x],max[son[x][0]]);
if(son[x][1]) max[x]=std::max(max[x],max[son[x][1]]);
}
inline void pushdown(int x)
{
if(rev[x])
{
if(son[x][0]) rev[son[x][0]]^=1;
if(son[x][1]) rev[son[x][1]]^=1;
rev[x]=0;
std::swap(son[x][0],son[x][1]);
}
}
inline bool isroot(int x)
{
return ((son[fa[x]][0]!=x)&&(son[fa[x]][1]!=x));
}
inline void rotate(int x)
{
int fa1=fa[x],fa2=fa[fa1],l;
l=son[fa1][0]==x?0:1;
int r=l^1;
if(!isroot(fa1))
{
if(son[fa2][0]==fa1) son[fa2][0]=x;
else son[fa2][1]=x;
}
fa[x]=fa2;
fa[fa1]=x;
fa[son[x][r]]=fa1;
son[fa1][l]=son[x][r];
son[x][r]=fa1;
pushup(fa1),pushup(x);
}
inline void splay(int x)
{
stk[top=1]=x;
for(int i=x;!isroot(i);i=fa[i]) stk[++top]=fa[i];
for(int i=top;i;i--) pushdown(stk[i]);
while(!isroot(x))
{
int y=fa[x],z=fa[y];
if(!isroot(y))
{
if((son[y][1]==x)^(son[z][1]==y)) rotate(x);
else rotate(y);
}
rotate(x);
}
}
inline void access(int x){for(int t=0;x;t=x,x=fa[x]) splay(x),son[x][1]=t,pushup(x);}
inline void makeroot(int x){access(x),splay(x),rev[x]^=1;}
inline int findroot(int x){access(x),splay(x);while(son[x][0])x=son[x][0];return x;}
inline void split(int x,int y){makeroot(x);access(y);splay(y);}
inline void cut(int x,int y){split(x,y);if(son[y][0]==x&&!son[x][1]) son[y][0]=0,fa[x]=0;}
inline void link(int x,int y){makeroot(x);fa[x]=y;}
inline bool check(int x,int y){return findroot(x)==findroot(y);}
}Tree[11];
inline void change(int u,int v,int col)
{
for(int i=1;i<=c;i++)
if(Tree[i].check(u,v))
{
Tree[i].split(u,v);
if(Tree[i].son[v][0]!=u||Tree[i].son[u][1]) continue;
if(i==col)
{
puts("Success.");
return;
}
if(d[u][col]>1||d[v][col]>1)
{
puts("Error 1.");
return;
}
if(Tree[col].check(u,v))
{
puts("Error 2.");
return;
}
Tree[i].cut(u,v);
Tree[col].link(u,v);
d[u][i]--,d[v][i]--;
d[u][col]++,d[v][col]++;
puts("Success.");
return;
}
puts("No such edge.");
}
int main()
{
scanf("%d%d%d%d",&n,&m,&c,&q);
for(int i=1;i<=n;i++)
scanf("%d",&val[i]);
for(int i=1;i<=m;i++)
{
int x,y,col;
scanf("%d%d%d",&x,&y,&col);
col++;
d[x][col]++,d[y][col]++;
Tree[col].link(x,y);
//printf("%d\n",Tree[col].checklink(x,y));
}
for(int i=1;i<=q;i++)
{
int opt,u,v,col;
scanf("%d",&opt);
if(!opt)
{
scanf("%d%d",&u,&v);
val[u]=v;
for(int j=1;j<=c;j++)
{
Tree[j].splay(u);
Tree[j].pushup(u);
}
}
if(opt==1)
{
scanf("%d%d%d",&u,&v,&col);
col++;
change(u,v,col);
}
if(opt==2)
{
scanf("%d%d%d",&col,&u,&v);
col++;
if(!Tree[col].check(u,v)) printf("-1\n");
else
{
Tree[col].split(u,v);
printf("%d\n",Tree[col].max[v]);
}
}
}
return 0;
}