【BZOJ2959】长跑(Link-Cut Tree,并查集)
2018-01-22 22:01
351 查看
【BZOJ2959】长跑(Link-Cut Tree,并查集)
题面
BZOJ题解
如果保证不出现环的话妥妥的\(LCT\)傻逼题
现在可能会出现环
环有什么影响?
那就可以沿着环把所有点全部走一遍吧
所以,相当于把环看成一个点来搞一搞
所以,维护一个并查集
记录一下每个点被缩成了哪个点
然后再用\(LCT\)维护缩点后的树就行啦
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<set> #include<map> #include<vector> #include<queue> using namespace std; #define MAX 320000 #define lson (t[x].ch[0]) #define rson (t[x].ch[1]) inline int read() { int x=0,t=1;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=-1,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return x*t; } struct Node { int ch[2],ff; int sum,rev,v; }t[MAX<<1]; int S[MAX<<1],top; int tot,n,m,a[MAX<<1]; int f[MAX<<1]; int ff[MAX<<1]; int getf(int x){return x==f[x]?x:f[x]=getf(f[x]);} int Getf(int x){return x==ff[x]?x:ff[x]=Getf(ff[x]);} bool isroot(int x){return t[getf(t[x].ff)].ch[0]!=x&&t[getf(t[x].ff)].ch[1]!=x;} void pushup(int x){t[x].sum=t[lson].sum+t[rson].sum+t[x].v;} void pushdown(int x) { if(!t[x].rev)return; swap(lson,rson); t[lson].rev^=1;t[rson].rev^=1; t[x].rev^=1; } void rotate(int x) { int y=getf(t[x].ff),z=getf(t[y].ff); int k=t[y].ch[1]==x; if(!isroot(y))t[z].ch[t[z].ch[1]==y]=x;t[x].ff=z; t[y].ch[k]=t[x].ch[k^1];t[t[x].ch[k^1]].ff=y; t[x].ch[k^1]=y;t[y].ff=x; pushup(y);pushup(x); } void Splay(int x) { S[top=1]=x=getf(x); for(int i=x;!isroot(i);i=getf(t[i].ff))S[++top]=getf(t[i].ff); while(top)pushdown(S[top--]); while(!isroot(x)) { int y=getf(t[x].ff),z=getf(t[y].ff); if(!isroot(y)) (t[y].ch[1]==x)^(t[z].ch[1]==y)?rotate(x):rotate(y); rotate(x); } } void access(int x){x=getf(x);for(int y=0;x;y=x,x=getf(t[x].ff))Splay(x),t[x].ch[1]=y,pushup(x);} void makeroot(int x){x=getf(x);access(x);Splay(x);t[x].rev^=1;} void split(int x,int y){x=getf(x);y=getf(y);makeroot(x);access(y);Splay(y);} void link(int x,int y){x=getf(x);y=getf(y);makeroot(x);t[x].ff=y;pushup(y);} int findroot(int x){getf(x);access(x);Splay(x);while(lson)x=lson;return x;} void dfs(int x) { f[getf(x)]=tot; t[tot].v+=t[x].v; t[tot].sum+=t[x].v; if(lson)dfs(lson); if(rson)dfs(rson); } void Link(int x,int y) { if(Getf(x)!=Getf(y))ff[Getf(x)]=Getf(y),link(getf(x),getf(y)); else { x=getf(x);y=getf(y); ++tot;ff[tot]=f[tot]=tot; split(x,y); dfs(y); } } void Modify(int u,int v) { makeroot(getf(u)); t[getf(u)].v-=a[u];a[u]=v; t[getf(u)].v+=a[u]; pushup(getf(u)); } int Query(int u,int v) { if(Getf(u)!=Getf(v))return -1; u=getf(u);v=getf(v); split(u,v); return t[v].sum; } int main() { tot=n=read();m=read(); for(int i=1;i<=n;++i)f[i]=ff[i]=i,t[i].v=a[i]=read(); int opt,u,v; while(m--) { opt=read();u=read();v=read(); if(opt==1)Link(u,v); else if(opt==2)Modify(u,v); else printf("%d\n",Query(u,v)); } return 0; }
相关文章推荐
- 【BZOJ2959】长跑(Link-Cut Tree,并查集)
- BZOJ 2959: 长跑 [lct 双连通分量 并查集]
- [BZOJ2959][清橙1379]长跑-LCT-并查集
- 【LCT+并查集】BZOJ2959[长跑]题解
- 【bzoj2959】长跑【LCT+并查集】
- BZOJ 2959 长跑 Link-Cut-Tree+并查集
- [BZOJ2959]长跑 LCT+双联通分量+并查集
- 【BZOJ3282】Tree (Link-Cut Tree)
- [bzoj3664][Noi2014]魔法森林 Link-Cut-Tree 并查集
- BZOJ 题目1036: [ZJOI2008]树的统计Count(Link Cut Tree,改动点权求两个最大值和最大值)
- 【BZOJ2959】长跑 LCT+并查集
- bzoj 2049(link cut tree)
- BZOJ 2049 [Sdoi2008]Cave 洞穴勘测 ——Link-Cut Tree
- 【BZOJ2002】弹飞绵羊(Link-Cut Tree)
- [BZOJ2959]长跑(LCT)
- 【BZOJ2049】[Sdoi2008]Cave 洞穴勘测【Link-Cut Tree】
- 【BZOJ4736】温暖会指引我们前行(Link-Cut Tree)
- BZOJ 2959: 长跑(LCT+并查集)
- BZOJ 2002 [Hnoi2010]Bounce 弹飞绵羊 ——Link-Cut Tree
- BZOJ2959: 长跑