• BZOJ 4668: 冷战 并查集启发式合并/LCT


    挺好想的,最简单的方法是并查集启发式合并,加暴力跳父亲。 

    然而,这个代码量比较小,比较好写,所以我写了 LCT,更具挑战性。

    #include <cstdio> 
    #include <algorithm> 
    #define N 1000004 
    #define lson t[x].ch[0] 
    #define rson t[x].ch[1] 
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;   
    int sta[N],n,m,p[N]; 
    struct Node { 
    	int ch[2],max,val,rev,f; 
    }t[N];  
    int find(int x) {
    	return p[x]==x?x:p[x]=find(p[x]); 
    }
    int get(int x) {
    	return t[t[x].f].ch[1]==x; 
    }  
    int isrt(int x) {
    	return !(t[t[x].f].ch[0]==x||t[t[x].f].ch[1]==x); 
    }
    void pushup(int x) {
    	t[x].max=t[x].val; 
    	t[x].max=max(max(t[lson].max,t[rson].max), t[x].max); 
    }  
    void mark(int x) {
    	if(!x) return; 
    	swap(lson, rson), t[x].rev^=1;  
    }
    void pushdown(int x) {
    	if(t[x].rev) mark(lson), mark(rson), t[x].rev=0; 
    }
    void rotate(int x) {  
    	int old=t[x].f,fold=t[old].f,which=get(x); 
    	if(!isrt(old)) 
    		t[fold].ch[t[fold].ch[1]==old]=x; 
    	t[old].ch[which]=t[x].ch[which^1], t[t[old].ch[which]].f=old; 
    	t[x].ch[which^1]=old,t[old].f=x,t[x].f=fold; 
    	pushup(old),pushup(x);  
    } 
    void splay(int x) {
    	int v=0,u=x,fa; 
    	for(sta[++v]=u;!isrt(u);u=t[u].f) sta[++v]=t[u].f; 
    	for(int i=v;i>=1;--i) pushdown(sta[i]); 
    	for(u=t[u].f;(fa=t[x].f)!=u;rotate(x)) 
    		if(t[fa].f!=u) 
    			rotate(get(fa)==get(x)?fa:x);     
    }
    void Access(int x) {
    	for(int y=0;x;y=x,x=t[x].f) { 
    		splay(x),rson=y,pushup(x);        
    	}
    }
    void makeroot(int x) {
    	Access(x),splay(x),mark(x); 
    } 
    void split(int x,int y) {
    	makeroot(x),Access(y),splay(y); 
    }
    void link(int x,int y) {   
    	makeroot(x), makeroot(y),t[x].f=y;  
    }
    int main() { 
    	int i,j,cc=0;  
    	scanf("%d%d",&n,&m); 
    	for(i=1;i<=n;++i) p[i]=i;    
    	int lastans=0,tot=n; 
    	for(i=1;i<=m;++i) {  
    		int op,x,y; 
    		scanf("%d%d%d",&op,&x,&y); 
    		x^=lastans,y^=lastans; 
    		if(op==0) {  
    			++cc; 
    			x=find(x),y=find(y); 
    			if(x!=y) {
    				++tot; 
    				p[x]=p[y]=p[tot]=tot;  
    				t[tot].val=cc;   
    				link(x,tot),link(tot,y);    
    			}
    		}
    		else { 
    			int xx=find(x),yy=find(y); 
    			if(xx!=yy) printf("0
    "),lastans=0; 
    			else { 
    				split(x,y);     
    				printf("%d
    ",lastans=t[y].max);   
    			}
    		}
    	}
    	return 0; 
    }
    

      

  • 相关阅读:
    lucene中的filter器群组及其缓存大盘点 猴子的天地 猴子的天地
    Lucene.net多字段多索引目录搜索
    lucene.net 应用资料
    lucene.net 详解
    java里面的值调用
    Linux中关于进程方面常用函数的区别
    Jsp页面实现文件上传下载
    编译carrot2发布
    Linux下vi的使用
    深入浅出SQL之左连接、右连接和全连接
  • 原文地址:https://www.cnblogs.com/guangheli/p/11431980.html
Copyright © 2020-2023  润新知