动态树~LCT总结
来源:互联网 发布:linux系统有哪些版本 编辑:程序博客网 时间:2024/04/30 14:35
这是我开的一套动态树专题:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=25242#overview
首先说一下什么是动态树。动态树可以维护一个动态的森林,支持树的合并(两棵合并成一棵),分离(把某个点和它父亲点分开),动态LCA,树上的点权和边权维护、查询(单点或者树上的一条路径),换根。
这里首先推荐杨哲的集训队作业:http://wenku.baidu.com/view/75906f160b4e767f5acfcedb 这里面对动态树的基本操作介绍比较全面,同时还带有相关证明。
看完论文以后,这里以HDOJ4010为例对LCT作个说明。
本题有四种操作:
1、如果x和y不在同一棵树上则在xy连边
2、如果x和y在同一棵树上并且x!=y则把x换为树根并把y和y的父亲分离
3、如果x和y在同一棵树上则x到y的路径上所有的点权值+w
4、如果x和y在同一棵树上则输出x到y路径上的最大值
非法则输出-1
根据YZ的作业,access是所有动态树所有操作的基础,一次access(u)操作会把从点u到根上的所有点按深度用一棵splay维护,左边比根深度小,右边比根大,那么要提取x到y的路径只要把x换成根再access(y)就可以,换根操作可以先access(x),splay(x)再把整棵splay翻转,因为splay(x)以后在splay上x的右子树是空的,翻转以后x就是深度最小的点,也就是根,这里的翻转可以打懒惰标记,同样,维护链上的和、极值也可以用同样的方法维护。
这样的话所有操作就是先access,再splay,打标记【没了
#include <cstdio>#include <iostream>using namespace std;#define N 300010#define INF (1<<30)struct node{node *p,*ch[2];int mx,rev,val,add;}nodes[N],*cur,*null;int n,m,u,v,w;node *newnode(int key){cur->p=cur->ch[0]=cur->ch[1]=null;cur->mx=cur->val=key;cur->rev=0;return cur++;}void init(){null=nodes;null->p=null->ch[0]=null->ch[1]=null;null->mx=null->val=-INF;null->add=0;null->rev=0;cur=nodes+1;}struct dynamictree{bool isroot(node *x)//判根{return x==null || x->p->ch[0]!=x && x->p->ch[1]!=x;}void pushup(node *x){x->mx=max(x->val,max(x->ch[0]->mx,x->ch[1]->mx));}void pushdown(node *x){if(x==null) return;if(x->rev){x->rev=0;if(x->ch[0]!=null) x->ch[0]->rev^=1;if(x->ch[1]!=null) x->ch[1]->rev^=1;swap(x->ch[0],x->ch[1]);}if(x->add){if(x->ch[0]!=null) x->ch[0]->add+=x->add,x->ch[0]->val+=x->add,x->ch[0]->mx+=x->add;if(x->ch[1]!=null) x->ch[1]->add+=x->add,x->ch[1]->val+=x->add,x->ch[1]->mx+=x->add;x->add=0;}}void rotate(node *x,int f){if(isroot(x)) return;node *y=x->p;y->ch[!f]=x->ch[f];x->p=y->p;if(x->ch[f]!=null) x->ch[f]->p=y;if(y!=null){if(y==y->p->ch[1]) y->p->ch[1]=x;else if(y==y->p->ch[0]) y->p->ch[0]=x;}x->ch[f]=y;y->p=x;pushup(y);}void splay(node *x){static node *sta[N];int top=1;sta[0]=x;for(node *y=x;!isroot(y);y=y->p)sta[top++]=y->p;while (top) pushdown(sta[--top]);while (!isroot(x)){node *y=x->p;if(isroot(y)) rotate(x,x==y->ch[0]);else{int f=y->p->ch[0]==y;if(y->ch[f]==x) rotate(x,!f);else rotate(y,f);rotate(x,f);}}pushup(x);}node *access(node *u){node *v=null;while (u!=null){splay(u);v->p=u;u->ch[1]=v;pushup(u);v=u;u=u->p;}return v;}node *link(node *u,node *v)//合并{access(u);splay(u);u->rev=1;u->p=v;}node *cut(node *u)//分离{access(u);splay(u);u->ch[0]=u->ch[0]->p=null;pushup(u);}void changeroot(node *u)//换根{access(u)->rev^=1;}node *getroot(node *u)//找根{access(u);splay(u);while (u->p!=null) u=u->p;splay(u);return u;}bool queryuv(node *u,node *v)//判断是否在同一子树{while (u->p!=null) u=u->p;while (v->p!=null) v=v->p;return u==v;}}splay;int eu[N],ev[N];int main (){while (scanf("%d",&n)!=-1){init();for(int i=1;i<n;i++)scanf("%d%d",&eu[i],&ev[i]);for(int i=1;i<=n;i++){int a;scanf("%d",&a);newnode(a);}for(int i=1;i<n;i++)splay.link(nodes+eu[i],nodes+ev[i]);scanf("%d",&m);for(int i=1;i<=m;i++){scanf("%d",&u);if(u==1){scanf("%d%d",&u,&v);if(splay.queryuv(nodes+u,nodes+v)){printf("-1\n");continue;}splay.link(nodes+u,nodes+v);}else if(u==2){scanf("%d%d",&u,&v);if(u==v || !splay.queryuv(nodes+u,nodes+v)){printf("-1\n");continue;}splay.changeroot(nodes+u);splay.cut(nodes+v);}else if(u==3){scanf("%d%d%d",&w,&u,&v);if(! splay.queryuv(nodes+u,nodes+v)){printf("-1\n");continue;}splay.changeroot(nodes+u);splay.access(nodes+v);node *q=splay.getroot(nodes+v);q->add+=w;q->mx+=w;q->val+=w;}else{scanf("%d%d",&u,&v);if(! splay.queryuv(nodes+u,nodes+v)){printf("-1\n");continue;}splay.changeroot(nodes+u);splay.access(nodes+v);printf("%d\n",splay.getroot(nodes+v)->mx);}}printf("\n");}return 0;}
- 动态树~LCT总结
- 动态树LCT总结
- 动态树LCT 模板
- lct动态树
- 专题总结:动态树 LCT(Link cut tree)
- 动态树LCT(SPOJ375)
- LCT 动态树 hdu 5002
- BZOJ1180 OTOCI(LCT动态树)
- LCT动态树学习小记
- lct总结
- LCT总结
- Link-Cut Tree(LCT) 模板总结 & 水题/模板题 动态树
- 动态树LCT||分块(BZOJ2002)
- 【动态树问题】LCT学习笔记
- poj 3237 Tree 树链剖分 动态树 LCT
- HDU 4010 动态树LCT学习
- 【动态树LCT】[SDOI2008]洞穴勘测
- [动态树 LCT] BZOJ 2157 旅游
- 未使用调试信息生成二进制文件
- memcached高可用工具memcached-ha
- 彻底转变流,第 1 部分
- Cobar的安装和配置步骤
- ThinkPHP3.0整合UCenter1.6 之(二)
- 动态树~LCT总结
- "Cannot refer to a non-final variable * inside an inner class defined in a different method"错误解析
- 彻底转变流,第 2 部分:优化 Java 内部 I/O
- VC运行库版本不同导致链接.LIB静态库时发生重复定义问题的一个案例分析和总结
- 【实用随记】头像区域
- 实现Django的全文检索功能(三):进一步学习Haystack
- 软件测试基础题及答案
- 思维导图
- 实现Django的全文检索功能(一):选择Whoosh全文检索引擎