码迷,mamicode.com
首页 > 其他好文 > 详细

[BZOJ2959]长跑

时间:2018-02-06 21:33:52      阅读:143      评论:0      收藏:0      [点我收藏+]

标签:php   cst   长跑   body   ++   link   tac   div   并查集   

BZOJ

sol

维护点的连通关系和双连通关系,双连通分量就可以缩成一个点,开一个并查集搞一搞。
所以注意每一次跳父亲都要找他在并查集里面的根,即所有的fa[x]都要写成find(fa[x])
像这种没有cut的LCT题目最好写并查集维护连通性,常数!

code

#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 150005;
int gi()
{
    int x=0,w=1;char ch=getchar();
    while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if (ch=='-') w=0,ch=getchar();
    while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return w?x:-x;
}
int n,m,fa[N],ch[2][N],rev[N],w[N],val[N],sum[N],con[N],scc[N],Stack[N],top;
int find(int x){return x==scc[x]?x:scc[x]=find(scc[x]);}
int Find(int x){return x==con[x]?x:con[x]=Find(con[x]);}
bool son(int x){return ch[1][find(fa[x])]==x;}
bool isroot(int x){return ch[0][find(fa[x])]!=x&&ch[1][find(fa[x])]!=x;}
void reverse(int x){if(!x)return;swap(ch[0][x],ch[1][x]);rev[x]^=1;}
void pushup(int x){sum[x]=sum[ch[0][x]]+sum[ch[1][x]]+val[x];}
void pushdown(int x){if(!rev[x])return;reverse(ch[0][x]);reverse(ch[1][x]);rev[x]=0;}
void rotate(int x)
{
    int y=find(fa[x]),z=find(fa[y]),c=son(x);
    ch[c][y]=ch[c^1][x];if (ch[c][y]) fa[ch[c][y]]=y;
    fa[x]=z;if (!isroot(y)) ch[son(y)][z]=x;
    ch[c^1][x]=y;fa[y]=x;pushup(y);
}
void splay(int x)
{
    Stack[top=1]=x;
    for (int y=x;!isroot(y);y=find(fa[y])) Stack[++top]=find(fa[y]);
    while (top) pushdown(Stack[top--]);
    for (int y=find(fa[x]);!isroot(x);rotate(x),y=find(fa[x]))
        if (!isroot(y)) son(x)^son(y)?rotate(x):rotate(y);
    pushup(x);
}
void access(int x){for (int y=0;x;y=x,x=find(fa[x])) splay(x),ch[1][x]=y,pushup(x);}
void makeroot(int x){access(x);splay(x);reverse(x);}
void split(int x,int y){makeroot(x);access(y);splay(y);}
void link(int x,int y){makeroot(x);fa[x]=y;}
void dfs(int x,int rt){if(!x)return;scc[find(x)]=rt;dfs(ch[0][x],rt);dfs(ch[1][x],rt);}
int main()
{
    n=gi();m=gi();
    for (int i=1;i<=n;++i) con[i]=scc[i]=i,w[i]=val[i]=gi();
    while (m--)
    {
        int opt=gi(),u=gi(),v=gi();
        if (opt==1)
        {
            u=find(u);v=find(v);
            if (Find(u)!=Find(v)) link(u,v),con[Find(u)]=Find(v);
            else{
                split(u,v);val[v]=sum[v];
                dfs(v,v);ch[0][v]=ch[1][v]=0;
            }
        }
        if (opt==2)
        {
            int fu=find(u);
            splay(fu);val[fu]+=v-w[u];w[u]=v;pushup(fu);
        }
        if (opt==3)
        {
            u=find(u);v=find(v);
            if (Find(u)^Find(v)) {puts("-1");continue;}
            split(u,v);printf("%d\n",sum[v]);
        }
    }
    return 0;
}

[BZOJ2959]长跑

标签:php   cst   长跑   body   ++   link   tac   div   并查集   

原文地址:https://www.cnblogs.com/zhoushuyu/p/8424129.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!