zoukankan      html  css  js  c++  java
  • BZOJ2959 长跑

    题目链接:戳我

    LCT维护树上连通块一类的题目。

    动态加边维护连通性最好还是用并查集来搞,时间复杂度貌似更优秀一点。

    主要难点是这道题目中有可能存在环,我们考虑缩点。我们要再开一个fa数组,来表示缩点之后的节点编号。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #define MAXN 500010
    using namespace std;
    int n,m,top,tot;
    int bcj[MAXN],fa[MAXN],s[MAXN],w[MAXN];
    struct Node{int ff,sum,rev,v,ch[2];}t[MAXN<<2];
    
    inline int find_bcj(int x){return bcj[x]==x?x:bcj[x]=find_bcj(bcj[x]);}//这个是并查集
    
    inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}//这个是缩点之后的
    
    inline bool isroot(int x){return t[find(t[x].ff)].ch[0]!=x&&t[find(t[x].ff)].ch[1]!=x;}
    
    inline void push_up(int x){t[x].sum=t[t[x].ch[0]].sum+t[t[x].ch[1]].sum+t[x].v;}
    
    inline void rotate(int x)
    {
        int y=find(t[x].ff);
        int z=find(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;
        push_up(y),push_up(x);
    }
    
    inline void push_down(int x)
    {
        if(t[x].rev)
        {
            swap(t[x].ch[0],t[x].ch[1]);
            t[t[x].ch[0]].rev^=1;
            t[t[x].ch[1]].rev^=1;
            t[x].rev^=1;
        }
    }
    
    inline void splay(int x)
    {
        s[top=1]=x=find(x);
        for(int i=x;!isroot(i);i=find(t[i].ff)) s[++top]=find(t[i].ff);
        while(top) push_down(s[top--]);
        while(!isroot(x))
        {
            int y=t[x].ff;
            int z=t[y].ff;
            if(!isroot(y))
                ((t[y].ch[0]==x)^(t[z].ch[0]==y))?rotate(x):rotate(y);
            rotate(x);
        }
    }
    
    inline void access(int x)
    {
        x=find(x);
        for(int y=0;x;y=x,x=find(t[x].ff))
            splay(x),t[x].ch[1]=y,push_up(x);
    }
    
    inline void makeroot(int x){x=find(x);access(x);splay(x);t[x].rev^=1;}
    
    inline void split(int x,int y){x=find(x),y=find(y);makeroot(x);access(y);splay(y);}
    
    inline void solve(int x,int ff)
    {
        fa[find(x)]=ff;
        t[ff].v+=t[x].v;
        t[ff].sum+=t[x].v;
        if(t[x].ch[0]) solve(t[x].ch[0],ff);
        if(t[x].ch[1]) solve(t[x].ch[1],ff);
    }
    
    inline void link(int x,int y)
    {
        int a=find_bcj(x),b=find_bcj(y);
        if(a==b)
        {
            x=find(x),y=find(y);
            ++tot;
            fa[tot]=bcj[tot]=tot;
            split(x,y);
            solve(y,tot);
        }
        else 
        {
            bcj[find_bcj(x)]=find_bcj(y);
            x=find(x),y=find(y);
            makeroot(x);
            t[x].ff=y;
        }
    }
    
    inline void update(int x,int k)
    {
        int ff=find(x);
        makeroot(ff);
        t[ff].v-=w[x];
        t[ff].v+=k;
        w[x]=k;
        push_up(find(ff));
    }
    
    inline int query(int x,int y)
    {
        int a=find_bcj(x),b=find_bcj(y);
        if(a!=b) return -1;
        a=find(x),b=find(y);
        split(a,b);
        return t[b].sum;
    }
    
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d%d",&n,&m);
        tot=n;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&w[i]);
            t[i].v=w[i];
            bcj[i]=fa[i]=i;
        }
        for(int i=1;i<=m;i++)
        {
            int p,a,b;
            scanf("%d%d%d",&p,&a,&b);
            //printf("p=%d a=%d b=%d
    ",p,a,b);
            if(p==1) link(a,b);
            else if(p==2) update(a,b);
            else if(p==3) printf("%d
    ",query(a,b));   
        }
        return 0;
    }
    
  • 相关阅读:
    dubbo-admin 2.0安装部署
    一文多发神器
    springboot整合druid踩坑记录
    thymeleaf中的重定向的绝对路径问题
    路径问题
    sp_executesql介绍和使用
    java.net.UnknownHostException: api.weixin.qq.com解决办法
    调用百度地图示例
    浅析分布式架构
    城乡医保用户角色未分配修改
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10447706.html
Copyright © 2011-2022 走看看