bzoj2816:[ZJOI2012]网络

传送门

直接对于每种颜色都建一棵LCT就行了,至于判断能否修改,有一个特殊情况就是修改前和修改后的颜色可能相同
还有就是修改点权记得update
代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
void read(int &x) {
	char ch; bool ok;
	for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
	for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
}
#define rg register
const int maxn=1e4+10,N=1e4;
map<int,int>mp;
struct LCT{
	int st[maxn],v[maxn],tag[maxn],mx[maxn],ch[maxn][2],f[maxn];
	int isroot(int x){return ch[f[x]][0]!=x&&ch[f[x]][1]!=x;}
	void update(int x){mx[x]=max(mx[ch[x][0]],max(mx[ch[x][1]],v[x]));}
	void reverse(int x){tag[x]^=1,swap(ch[x][0],ch[x][1]);}
	void pushdown(int x){
		if(tag[x]){
			if(ch[x][0])reverse(ch[x][0]);
			if(ch[x][1])reverse(ch[x][1]);
			tag[x]^=1;
		}
	}
	void move(int x){
		int fa=f[x],faa=f[fa],tmp=ch[fa][1]==x;
		if(!isroot(fa))ch[faa][ch[faa][1]==fa]=x;
		ch[fa][tmp]=ch[x][tmp^1],f[ch[x][tmp^1]]=fa;
		ch[x][tmp^1]=fa,f[fa]=x,f[x]=faa;
		update(fa),update(x);
	}
	void splay(int x){
		int z=0,y=x;st[++z]=y;
		while(!isroot(y))st[++z]=y=f[y];
		while(z)pushdown(st[z]),z--;
		while(!isroot(x)){
			y=f[x],z=f[y];
			if(!isroot(y)){
				if((ch[y][0]==x)^(ch[z][0]==y))move(y);
				else move(x);
			}
			move(x);
		}
		update(x);
	}
	void access(int x){
		int y=0;
		while(x){
			splay(x),ch[x][1]=y;
			update(x),y=x,x=f[x];
		}
	}
	int findroot(int x){
		access(x),splay(x);int now=x;
		while(ch[now][0])pushdown(now),now=ch[now][0];
		return pushdown(now),splay(now),now;
	}
	void makeroot(int x){access(x),splay(x),reverse(x);}
	void split(int x,int y){makeroot(x),access(y),splay(y);}
	void link(int x,int y){makeroot(x),f[x]=y;}
	void cut(int x,int y){split(x,y),ch[y][0]=f[x]=0,update(y);}
}c[15];
int n,m,col,k,val[maxn],tot[maxn][15];
int main(){
	read(n),read(m),read(col),read(k);
	for(rg int i=1;i<=n;i++){
		read(val[i]);
		for(rg int j=1;j<=col;j++)c[j].v[i]=val[i];
	}
	for(rg int i=1,x,y,z;i<=m;i++){
		read(x),read(y),read(z),z++;
		c[z].link(x,y);mp[x*N+y]=mp[y*N+x]=z;
		tot[x][z]++,tot[y][z]++;
	}
	for(rg int i=1,op,x,y,z;i<=k;i++){
		read(op);
		if(op==0){
			read(x),read(y);
			for(rg int j=1;j<=col;j++)c[j].access(x),c[j].v[x]=y,c[j].splay(x);
		}
		if(op==1){
			read(x),read(y),read(z);int now=mp[x*N+y];z++;
			if(!now){printf("No such edge.\n");continue;}
			tot[x][z]++,tot[y][z]++,tot[x][now]--,tot[y][now]--;
			if(tot[x][z]>2||tot[y][z]>2){
				tot[x][z]--,tot[y][z]--,tot[x][now]++,tot[y][now]++;
				printf("Error 1.\n");continue;
			}
			if(c[z].findroot(x)==c[z].findroot(y)&&now!=z){
				tot[x][z]--,tot[y][z]--,tot[x][now]++,tot[y][now]++;
				printf("Error 2.\n");continue;
			}
			c[now].cut(x,y),c[z].link(x,y),mp[x*N+y]=mp[y*N+x]=z;
			printf("Success.\n");
		}
		if(op==2){
			read(z),read(x),read(y),z++;
			if(c[z].findroot(x)!=c[z].findroot(y)){printf("-1\n");continue;}
			c[z].split(x,y),printf("%d\n",c[z].mx[y]);
		}
	}
}
posted @ 2019-05-27 11:10  蒟蒻--lichenxi  阅读(192)  评论(0编辑  收藏  举报