[BZOJ2049]洞穴勘测[BZOJ2157]旅游Link-Cut Tree模板题
来源:互联网 发布:开淘宝微店能赚钱吗 编辑:程序博客网 时间:2024/05/21 15:55
第一次写LCT,先来两道模板题,因为上个月被三道区间维护的超级工业的splay搞傻了,吸取了很多教训(见前几篇博客),所以LCT写得很顺啊,这里要感谢hzwer的题解。
BZOJ 2049:给出一颗树,每次加一条边或者删除一条边,询问两点的连通性。
这是一眼题,最裸的,纯天然的LCT,如果你不会先去看论文吧。半年以前看LCT感觉是一个非常高端的东西,当时反正看不懂,而TTY又有LCT爷的称号,写LCT都不用调,自然是伏地%。今天写了写发现还好。
废话不多说,查连通性就判断两个点的树的根是不是相等就可以了。
#include<ctime>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<iostream>#include<string>#include<cassert>#include<cmath>#include<vector>#include<queue>#include<stack>#include<map>#include<climits>#define X first#define Y second#define DB double#define MP make_pair#define LL long long#define pb push_back#define sqr(_) ((_)*(_))#define INF 0x3f3f3f3f#define pii pair<int,int>#define pdd pair<DB,DB>#define ull unsigned LL#define DEBUG(...) fprintf(stderr,__VA_ARGS__)using namespace std;void Read(int& x){ x=0;int flag=0;char c; while(c=getchar()) { if(c>='0'&&c<='9')x*=10,x+=c-'0',flag=1; else if(flag)break; }}const int MAXN=10010;int n,m;char s[10];struct Link_Cut_Tree{ int fa[MAXN],son[MAXN][2],rev[MAXN],top,st[MAXN]; Link_Cut_Tree(){ memset(fa,0,sizeof(fa)); memset(son,0,sizeof(son)); memset(rev,0,sizeof(rev)); top=0; } bool isroot(int x) { return son[fa[x]][0]!=x&&son[fa[x]][1]!=x; } void rotate(int x) { int y=fa[x],d=(x==son[y][1]); if(fa[y]&&!isroot(y)) { son[fa[y]][son[fa[y]][1]==y]=x; } assert(x!=fa[y]); fa[x]=fa[y]; assert(y!=x); fa[y]=x; son[y][d]=son[x][d^1]; if(son[x][d^1])fa[son[x][d^1]]=y; son[x][d^1]=y; } void update_rev(int now) { rev[now]^=1; swap(son[now][0],son[now][1]); } void push_down(int x) { if(rev[x]) { rev[x]^=1; update_rev(son[x][0]); update_rev(son[x][1]); } } void splay(int x) { st[++top]=x; int tmp=x; while(!isroot(tmp)) { st[++top]=fa[tmp]; tmp=fa[tmp]; } while(top) { push_down(st[top]); top--; } while(!isroot(x)) { int y=fa[x]; if(isroot(y)) { rotate(x); break; } rotate(x); } } void aksess(int x) { int tmp=0; while(x) { splay(x); son[x][1]=tmp; tmp=x; x=fa[x]; } } void beroot(int x) { aksess(x); splay(x); update_rev(x); } void link(int x,int y) { beroot(x); fa[x]=y; splay(x); } void cut(int x,int y) { beroot(x); aksess(y); splay(y); son[y][0]=fa[x]=0; } int find(int x) { aksess(x); splay(x); int tmp=x; while(tmp) { if(!son[tmp][0]) return tmp; tmp=son[tmp][0]; } }}LCT;int main(){#ifndef ONLINE_JUDGE freopen("cave.in","r",stdin); freopen("cave.out","w",stdout);#endif Read(n);Read(m); for(int i=1;i<=m;i++) { scanf("%s",s); if(s[0]=='Q') { int a,b; Read(a);Read(b); if(LCT.find(a)==LCT.find(b)) puts("Yes"); else puts("No"); } else if(s[0]=='D') { int a,b; Read(a);Read(b); LCT.cut(a,b); } else { int a,b; Read(a);Read(b); LCT.link(a,b); } }}
BZOJ 2157:给出一棵树,每次可以更改边权,路径边权置负,查询路径权值和,路径权值最大值,路径权值最小值。
虽然这一题既没有加边也没有删边,但是为了多A一道题而且能练习一下打改值标记的splay,就没有写树链剖分了。
LCT是不能维护边的权值的,我们考虑把边建成点,第i号边就是第n+i号点,然后也是模板题了。这里树上路径问题与区间维护问题有一点点不同,区间维护的splay要设两个虚点,取出区间就是把一个点splay到根,另一个点splay到根的右儿子,取出右儿子的子树。而LCT直接换根,aksess,再splay就可以了。
#include<ctime>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<iostream>#include<string>#include<cassert>#include<cmath>#include<vector>#include<queue>#include<stack>#include<map>#include<climits>#define X first#define Y second#define DB double#define MP make_pair#define LL long long#define pb push_back#define lc son[now][0]#define rc son[now][1]#define sqr(_) ((_)*(_))#define INF 0x3f3f3f3f#define pii pair<int,int>#define pdd pair<DB,DB>#define ull unsigned LL#define DEBUG(...) fprintf(stderr,__VA_ARGS__)using namespace std;void Read(int& x){ x=0;int flag=0,sgn=1;char c; while(c=getchar()) { if(c=='-')sgn=-1; else if(c>='0'&&c<='9')x*=10,x+=c-'0',flag=1; else if(flag)break; } x*=sgn;}const int MAXN=200011;char s[10];int n,m,f[MAXN];struct Link_Cut_Tree{ int fa[MAXN],son[MAXN][2],st[MAXN],top,mx[MAXN],sum[MAXN],mn[MAXN],v[MAXN]; bool rev[MAXN],neg[MAXN]; Link_Cut_Tree(){ top=0; memset(rev,0,sizeof(rev)); memset(neg,0,sizeof(neg)); memset(fa,0,sizeof(fa)); memset(son,0,sizeof(son)); memset(mx,-INF,sizeof(mx));memset(mn,INF,sizeof(mn)); memset(sum,0,sizeof(sum)); memset(v,0,sizeof(v)); } void update_rev(int now) { rev[now]^=1; swap(lc,rc); } void update_neg(int now) { neg[now]^=1; sum[now]*=-1; swap(mx[now],mn[now]); mx[now]*=-1; mn[now]*=-1; v[now]*=-1; } void update(int now) { sum[now]=sum[lc]+sum[rc]+v[now]; mn[now]=min(mn[lc],mn[rc]); mx[now]=max(mx[rc],mx[lc]); if(now>n) { mn[now]=min(mn[now],v[now]); mx[now]=max(mx[now],v[now]); } } void push_down(int now) { if(rev[now]) { rev[now]^=1; update_rev(lc); update_rev(rc); } if(neg[now]) { neg[now]^=1; update_neg(lc); update_neg(rc); } } bool isroot(int x) { return son[fa[x]][0]!=x&&son[fa[x]][1]!=x; } void rotate(int x) { int y=fa[x],d=(son[y][1]==x); if(fa[y]&&!isroot(y)) son[fa[y]][son[fa[y]][1]==y]=x; fa[x]=fa[y]; fa[y]=x; son[y][d]=son[x][d^1]; if(son[x][d^1]) fa[son[x][d^1]]=y; son[x][d^1]=y; update(y);update(x); } void splay(int x) { top=0; st[++top]=x; int tmp=x; while(!isroot(tmp)) { st[++top]=fa[tmp]; tmp=fa[tmp]; } while(top) push_down(st[top--]); while(!isroot(x)) rotate(x); } void aksess(int x) { int t=0; while(x) { splay(x); son[x][1]=t; update(x); t=x;x=fa[x]; } } void beroot(int x) { aksess(x); splay(x); update_rev(x); } void link(int x,int y) { beroot(x); fa[x]=y; splay(x); } void split(int x,int y) { beroot(x); aksess(y); splay(y); }}LCT;int main(){#ifndef ONLINE_JUDGE freopen("tour.in","r",stdin); freopen("tour.out","w",stdout);#endif scanf("%d",&n); int id=n; for(int i=1;i<n;i++) { //DEBUG("%d\n",i); int a,b,c; scanf("%d %d %d",&a,&b,&c); a++,b++; LCT.v[++id]=c,LCT.update(id);//插节点注意update f[i]=id; LCT.link(a,id),LCT.link(b,id); } scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%s",s); int x,y; Read(x),Read(y); if(s[0]=='C') { LCT.splay(f[x]); LCT.v[f[x]]=y; LCT.update(f[x]); } else if(s[0]=='N') { LCT.split(x+1,y+1); LCT.update_neg(y+1); } else if(s[0]=='S') { LCT.split(x+1,y+1); printf("%d\n",LCT.sum[y+1]); } else if(s[1]=='A') { LCT.split(x+1,y+1); printf("%d\n",LCT.mx[y+1]); } else { LCT.split(x+1,y+1); printf("%d\n",LCT.mn[y+1]); } }}
0 0
- [BZOJ2049]洞穴勘测[BZOJ2157]旅游Link-Cut Tree模板题
- 【BZOJ2049】洞穴勘测(Link-Cut Tree)
- 【BZOJ2049】[Sdoi2008]Cave 洞穴勘测 Link-Cut-Tree
- bzoj2049 [Sdoi2008]Cave 洞穴勘测 (Link Cut Tree)
- 【BZOJ2049】[Sdoi2008]Cave 洞穴勘测【Link-Cut Tree】
- BZOJ2049: [Sdoi2008]Cave 洞穴勘测 Link-cut-tree
- [bzoj2049][Sdoi2008]Cave 洞穴勘测 Link-Cut-Tree
- 【SDOI2008】【link-cut tree】洞穴勘测
- BZOJ2157【Link Cut Tree】
- bzoj 2049: [Sdoi2008]Cave 洞穴勘测 (link-cut-tree)
- BZOJ 2049 洞穴勘测 Link-Cut-Tree(LCT)
- bzoj 2049 SDOI 2008 Cave 洞穴勘测 [Link-Cut Tree]
- bzoj 2049: [Sdoi2008]Cave 洞穴勘测 link cut tree
- BZOJ 2049: [Sdoi2008]Cave 洞穴勘测 link cut tree
- bzoj2049洞穴勘测(lct模板题,lct详解)
- 【BZOJ2049】洞穴勘测(SDOI2008)-LCT真·模板题
- BZOJ 2049 [Sdoi2008]Cave 洞穴勘测 link cut trees 模板题
- bzoj2049 洞穴勘测 lct
- 流媒体技术
- CodeForces NO.197B Limit
- round、ceil、floor
- 转发和重定向的区别
- HTML5:定制表单
- [BZOJ2049]洞穴勘测[BZOJ2157]旅游Link-Cut Tree模板题
- Android Annotation基础教程
- mysql
- 什么是不可修改对象(Immutable Object)?你能否写一个例子?
- 架构师主要工作
- 【BZOJ3326】数数 数学题
- struts2的form提交时action属性的配置
- Dreamweaver 支持 scss 设置
- Android ListView GridView 错位