• 【题解】[ZJOI2012]网络


    [ZJOI2012]网络

    ( ext{Solution:})

    很明显对着颜色分别维护 (LCT,) 想法在看到颜色的数据范围后也得到了证实。

    那么,怎么维护?

    有显然的断边连边操作,还要维护一下链上最大值,直接上 (LCT.)

    但是题目中的特殊情况很难判断,提出一些小坑:

    有可能删掉和加上的边是同一种颜色,所以要特判,否则先判就会测成 Error 1.

    如果用 set 去维护每个点连出去的边的话,会发生一些奇怪的错误,可能是因为判断重复的时候有编号一样但颜色不一样的边?

    这个地方用 map 处理会更好一些,但要注意尽量用 map.count 访问,因为有时候用下标访问会新建一个元素导致判空错误。

    #include<bits/stdc++.h>
    using namespace std;
    const int INF = 0x3f3f3f3f ;
    const int N=5e5+10;
    int n,m,v[N],st[N],C,k,CC[N][10];
    int mx[N],ch[N][2],f[N],rev[N];
    struct Node{
    	int u,v;
    	bool operator<(const Node&B)const{
    		return u==B.u?v<B.v:u<B.u;
    	}
    	Node(int xx=0,int yy=0){u=xx,v=yy;}
    };
    map<Node,int>mp;
    inline int Max(int x,int y){return x>y?x:y;}
    inline int Min(int x,int y){return x<y?x:y;}
    inline void pushup(int x){mx[x]=Max(Max(mx[ch[x][0]],mx[ch[x][1]]),v[x]);}
    inline void pushr(int x){
    	rev[x]^=1;
    	int t=ch[x][0];
    	ch[x][0]=ch[x][1];
    	ch[x][1]=t;
    }
    inline bool nroot(int x){return ch[f[x]][0]==x||ch[f[x]][1]==x;}
    inline void rotate(int x){
    	int y=f[x],z=f[y],k=(ch[y][1]==x),w=ch[x][k^1];
    	if(nroot(y))ch[z][ch[z][1]==y]=x;ch[x][k^1]=y;ch[y][k]=w;
    	if(w)f[w]=y;f[y]=x;f[x]=z;pushup(y);pushup(x);
    }
    inline void pushdown(int x){
    	if(rev[x]){
    		if(ch[x][0])pushr(ch[x][0]);
    		if(ch[x][1])pushr(ch[x][1]);
    		rev[x]^=1;
    	}
    }
    inline void splay(int x){
    	int y=x,z=0;
    	st[++z]=y;
    	while(nroot(y))st[++z]=y=f[y];
    	while(z)pushdown(st[z--]);
    	while(nroot(x)){
    		y=f[x];z=f[y];
    		if(nroot(y))rotate((ch[y][0]==x)^(ch[z][0]==y)?x:y);
    		rotate(x);
    	}
    	pushup(x);
    }
    inline void access(int x){
    	for(int y=0;x;y=x,x=f[x]){
    		splay(x),ch[x][1]=y;pushup(x);
    	}
    }
    inline void makeroot(int x){
    	access(x);splay(x);pushr(x);
    }
    int findroot(int x){
    	access(x);splay(x);
    	while(ch[x][0])pushdown(x),x=ch[x][0];
    	splay(x);return x;
    }
    inline void split(int x,int y){
    	makeroot(x);access(y);splay(y);
    }
    inline void link(int x,int y){
    	makeroot(x);
    	if(findroot(y)!=x)f[x]=y;
    }
    inline void cut(int x,int y){
    	makeroot(x);
    	if(findroot(y)==x&&f[y]==x&&!ch[y][0]){
    		f[y]=ch[x][1]=0;
    		pushup(x);
    	}
    }
    int main(){
    	scanf("%d%d%d%d",&n,&m,&C,&k);
    	for(int i=1;i<=n;++i)scanf("%d",&v[i]);
    	for(int i=1;i<=n;++i)
    		for(int j=0;j<C;++j)
    			v[i+j*n]=v[i];
    	for(int i=1;i<=m;++i){
    		int u,v,c;
    		scanf("%d%d%d",&u,&v,&c);
    		mp[Node(u,v)]=c;mp[Node(v,u)]=c;
    		CC[u][c]++;CC[v][c]++;
    		link(u+c*n,v+c*n);
    	}
    	for(int jjj=1;jjj<=k;++jjj){
    		int opt,x,y,z;
    		scanf("%d%d%d",&opt,&x,&y);
    		if(opt==0){
    			for(int i=0;i<C;++i)splay(x+i*n),v[x+i*n]=y;
    			continue;
    		}
    		if(opt==1){
    			int u=x,v=y;
    			scanf("%d",&z);
    			Node edge1=Node(x,y);
    			Node edge2=Node(y,x);
    			if(!mp.count(edge1)||!mp.count(edge2)){
    				puts("No such edge.");
    				continue;
    			}
    			int Col=mp[edge1];
    			if(Col==z){
    				puts("Success.");
    				continue;
    			}
    			if(CC[u][z]==2){
    				puts("Error 1.");
    				continue;
    			}
    			if(CC[v][z]==2){
    				puts("Error 1.");
    				continue;
    			}
    			makeroot(u+z*n);
    			int fv=findroot(v+z*n);
    			if(fv==u+z*n){
    				puts("Error 2.");
    				continue;
    			}
    			mp.erase(edge1);
    			mp.erase(edge2);
    			mp[edge1]=z;
    			mp[edge2]=z;
    			cut(u+Col*n,v+Col*n);
    			CC[u][Col]--;
    			CC[u][z]++;
    			link(u+z*n,v+z*n);
    			CC[v][Col]--;
    			CC[v][z]++;
    			puts("Success.");
    			continue;
    		}
    		if(opt==2){
    			scanf("%d",&z);
    			int u=y+x*n,v=z+x*n;
    			makeroot(v);
    			int fv=findroot(v);
    			int fu=findroot(u);
    			if(fu!=fv){
    				puts("-1");
    				continue;
    			}
    			split(u,v);
    			printf("%d
    ",mx[v]);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Java 将数字转为16进制,然后转为字符串类型 将空格去掉。终结版
    Java 将数字转为16进制,然后转为字符串类型
    Java 数组转字符
    Apple Reject
    NSInternalInconsistencyException
    svn报错cleanup failed–previous operation has not finished; run cleanup if it was interrupted的解决办法
    CSS伪类选择器 奇偶匹配nth-child(even)
    常用css代码(scss mixin)
    织梦网站给栏目添加自定义字段图文详解
    css怎么解决表格边框线重复问题
  • 原文地址:https://www.cnblogs.com/h-lka/p/15062492.html
Copyright © 2020-2023  润新知