zoukankan      html  css  js  c++  java
  • 【模板篇】Link Cut Tree模板(指针)

    网上一片一片的LCT都是数组写的 orz
    用指针写splay的人想用指针写LCT找板子都不好找QAQ
    所以能A题了之后自然要来回报社会, 把自己的板子丢上来(然而根本没有人会看)

    LCT讲解就省省吧, 我这种蒟蒻也基本讲不清楚, 就扔个板子算了
    板子里也没什么注释, 因为函数的命名和世界的主流命名规范是一样的..

    那就这样吧.. 贴两道题的板子.
    第一个是SDOI2008 Cave洞穴勘测, 一道简单判断连通性的LCT裸题.
    三种操作;

    1. 连x,y 保证连完还是棵树
    2. 断x,y 保证<x,y>边存在
    3. 询问x,y是否联通
      然而据说用不路径压缩的并查集可过(考场上我估计就写这个了

    代码:

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int N=20101;
    inline int gn(int a=0,char c=0){
    	for(;c<'0'||c>'9';c=getchar());
    	for(;c>47&&c<58;c=getchar())a=a*10+c-48;return a;
    }
    struct node{
    	node *fa,*ch[2];
    	bool rev;
    	bool getwh();
    	bool isroot();
    	void pushdown();
    	void setch(bool wh,node* child);
    }pool[N],*null; int tot;
    bool node::getwh(){
    	return fa->ch[1]==this;
    }
    bool node::isroot(){
    	return fa==null||(fa->ch[0]!=this&&fa->ch[1]!=this);
    }
    void node::pushdown(){
    	if(null==this||!rev) return;
    	swap(ch[0],ch[1]);
    	ch[0]->rev^=1; ch[1]->rev^=1;
    	rev=0;
    }
    void node::setch(bool wh,node* child){
    	pushdown(); ch[wh]=child;
    	if(null!=child) child->fa=this;
    }
    void init(){
    	null=pool; null->rev=0;
    	null->fa=null->ch[0]=null->ch[1]=null;
    }
    node* newnode(){
    	node* x=pool+ ++tot; x->rev=0;
    	x->ch[0]=x->ch[1]=x->fa=null;
    	return x;
    }
    void rotat(node* x){
    	node *fa=x->fa,*fafa=fa->fa;
    	if(fafa!=null) fafa->pushdown();
    	fa->pushdown(); x->pushdown();
    	int wh=x->getwh();
    	if(fa->isroot()) x->fa=fa->fa;
    	else fafa->setch(fa->getwh(),x);
    	fa->setch(wh,x->ch[wh^1]);
    	x->setch(wh^1,fa);
    }
    void fix(node* x){
    	if(!x->isroot()) fix(x->fa);
    	x->pushdown();
    }
    void splay(node* x){
    	fix(x);
    	for(;!x->isroot();rotat(x))
    		if(!x->fa->isroot())
    			x->getwh()==x->fa->getwh()?rotat(x->fa):rotat(x);
    }
    node* access(node* x){
    	node* y=null;
    	for(;x!=null;x=x->fa){
    		splay(x); x->ch[1]=y; y=x;
    	}
    	return y;
    }
    void makeroot(node* x){
    	access(x)->rev^=1;
    	splay(x);
    }
    void link(node* x,node* y){
    	makeroot(x); x->fa=y;
    }
    void cut(node* x,node* y){
    	makeroot(x); access(y); splay(y);
    	x->fa=y->ch[0]=null;
    }
    node* Find(node* x){
    	for(access(x),splay(x);x->ch[0]!=null;x->pushdown(),x=x->ch[0]);
    	return x;
    }
    int main(){ init();
    	int n=gn(),m=gn();
    	for(int i=1;i<=n;++i) newnode();
    	char opt[123];
    	for(int i=1;i<=m;++i){
    		scanf("%s",opt);
    		int x=gn(),y=gn();
    		node *X=pool+x,*Y=pool+y;
    		if(opt[0]=='Q')
    			puts(Find(X)==Find(Y)?"Yes":"No");
    		else if(opt[0]=='C')
    			link(X,Y);
    		else cut(X,Y);
    	}	
    }
    

    然后另一道是luogu的模板题, 这个是带点权的
    (如果带边权的话还是化边为点...)
    四种操作:

    1. 查询x,y路径的异或和
    2. 连x,y 已连通则忽略
    3. 断x,y 不保证x,y间有边
    4. 单点修改

    代码:

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int N=300020;
    inline int gn(int a=0,char c=0){
    	for(;c<'0'||c>'9';c=getchar());
    	for(;c>47&&c<58;c=getchar())a=a*10+c-48;return a;
    }
    struct node{
    	node *fa,*ch[2];
    	bool rev; int xum,xx;
    	bool getwh(){return fa->ch[1]==this;}
    	bool isroot();
    	void update(){
    		xum=ch[0]->xum^ch[1]->xum^xx;
    	}
    	void pushdown();
    	void setch(bool wh,node* child);
    }pool[N],*null;
    int tot;
    bool node::isroot(){
    	return fa==null||(fa->ch[0]!=this&&fa->ch[1]!=this);
    }
    void node::pushdown(){
    	if(this==null||!rev) return;
    	swap(ch[0],ch[1]);
    	ch[0]->rev^=1;
    	ch[1]->rev^=1;
    	rev=0;
    }
    void node::setch(bool wh,node* child){
    	pushdown(); ch[wh]=child;
    	if(child!=null) child->fa=this;
    }
    void init(){
    	null=pool; null->ch[0]=null->ch[1]=null->fa=null; null->rev=0;
    }
    node* newnode(int val){
    	node* x=pool+ ++tot; x->xx=val;
    	x->ch[0]=x->ch[1]=x->fa=null;
    	x->rev=0; return x;
    }
    void rotat(node* x){
    	node *fa=x->fa,*fafa=fa->fa;
    	if(!fa->isroot()) fafa->pushdown();
    	fa->pushdown(); x->pushdown();
    	int wh=x->getwh();
    	fa->setch(wh,x->ch[wh^1]);
    	if(fa->isroot()) x->fa=fa->fa;
    	else fafa->setch(fa->getwh(),x);
    	x->setch(wh^1,fa);
    	fa->update(); x->update();
    }
    void fix(node* x){
    	if(!x->isroot()) fix(x->fa);
    	x->pushdown();
    }
    void splay(node *x){
    	fix(x);
    	for(;!x->isroot();rotat(x))
    		if(!x->fa->isroot())
    			x->getwh()==x->fa->getwh()?rotat(x->fa):rotat(x);
    	x->update();
    }
    node* access(node* x){
    	node* y=null;
    	for(;x!=null;x=x->fa){
    		splay(x);
    		x->ch[1]=y;
    		x->update(); 
    		y=x;
    	}
    	return y;
    }
    void makeroot(node* x){
    	access(x)->rev=1; splay(x);
    }
    void link(node* x,node* y){
    	makeroot(x);
    	x->fa=y;
    //	access(x);
    }
    void cut(node* x,node* y){
    	makeroot(x); access(y); splay(y);
    	x->fa=y->ch[0]=null;
    }
    node* Find(node* x){
    	for(access(x),splay(x);x->ch[0]!=null;x->pushdown(),x=x->ch[0]);
    	return x;
    }
    void change(node* x,int y){
    	access(x); splay(x);
    	x->xx=y; x->update();
    }
    int query(node* x,node* y){
    	makeroot(x);
    	access(y);
    	splay(y);
    	return y->xum;
    }
    int main(){
    	init();
    	int n=gn(),m=gn();
    	for(int i=1;i<=n;++i) newnode(gn());
    	for(int i=1;i<=m;++i){
    		int opt=gn(),x=gn(),y=gn();
    		node *X=pool+x,*Y=opt==3?null:pool+y;
    		switch(opt){
    			case 0:
    				printf("%d
    ",query(X,Y));
    				break;
    			case 1:
    				if(Find(X)!=Find(Y))
    					link(X,Y);
    				break;
    			case 2:
    				if(Find(X)==Find(Y))
    					cut(X,Y);
    				break;
    			case 3:
    				change(X,y);
    				break;
    		}
    	}
    }
    

    就这样吧...

  • 相关阅读:
    基于正方系统的抢课软件教程系列一模拟登录1
    基于正方系统的抢课软件教程系列二正则表达式使用
    基于正方系统的抢课软件教程系列一模拟登录3之验证码识别
    eCos中断模型
    eCos下针对MIPS指令集的backtrace
    开源许可证GPL
    获取ListView中的ImageButton
    Rancher v2.4.8 容器管理平台集群搭建(基于k8s)
    Linux awk 替换文本字符串内容
    go: go.mod file not found in current directory or any parent directory; see 'go help mod 解决
  • 原文地址:https://www.cnblogs.com/enzymii/p/8512335.html
Copyright © 2011-2022 走看看