• bzoj 2959: 长跑


    bzoj 2959: 长跑

    可以看作是这道题的加强版:https://www.luogu.org/problemnew/show/P2542

    看到动态维护(Tarjan)缩点就考虑使用(LCT),使用一个并查集(f)表示点(i)所在的点双的“标志”点是哪一个,(link)时分类讨论一下即可

    然后这题卡常,我们无法使用(findroot),于是考虑再用一个并查集表示两点之间的连通性即可

    剩下的就和那个弱化版差不多了

    #include<iostream>
    #include<string.h>
    #include<string>
    #include<stdio.h>
    #include<algorithm>
    #include<vector>
    #include<math.h>
    #include<queue>
    #include<set>
    #include<map>
    using namespace std;
    typedef long long ll;
    typedef long double db;
    const int N=10000;
    const db pi=acos(-1.0);
    #define lowbit(x) (x)&(-x)
    #define sqr(x) (x)*(x)
    #define rep(i,a,b) for (register int i=a;i<=b;i++)
    #define per(i,a,b) for (register int i=a;i>=b;i--)
    #define fir first
    #define sec second
    #define mp(a,b) make_pair(a,b)
    #define pb(a) push_back(a)
    #define maxd 998244353
    #define eps 1e-8
    int n,m,fa[150050],con[150050],f[150050],tag[150050],ch[150050][2];
    int val[150050],sum[150050],w[150050];
    
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
        while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
        return x*f;
    }
    
    int find(int x) 
    {
        if (f[x]==x) return x;
        f[x]=find(f[x]);
        return f[x];
    }
    
    int findcon(int x)
    {
        if (con[x]==x) return x;
        con[x]=findcon(con[x]);
        return con[x];
    }
    
    bool isroot(int x) 
    {
        int fx=find(fa[x]);
        return ((ch[fx][0]!=x) && (ch[fx][1]!=x));
    }
    
    void pushup(int x) {sum[x]=w[x]+sum[ch[x][0]]+sum[ch[x][1]];}
    void puttag(int x) {swap(ch[x][0],ch[x][1]);tag[x]^=1;}
    void pushdown(int x)
    {
        if (tag[x])
        {
            if (ch[x][0]) puttag(ch[x][0]);
            if (ch[x][1]) puttag(ch[x][1]);
            tag[x]=0;
        }
    }
    
    void update(int x)
    {
        //if (x==1) cout << "NOW " << ch[x][0] << " " << ch[x][1] << endl;
        if (!isroot(x)) update(find(fa[x]));pushdown(x);
    }
    
    void rotate(int x)
    {
        int y=find(fa[x]),z=find(fa[y]),k=(ch[y][1]==x),w=ch[x][k^1];
        if (!isroot(y)) ch[z][ch[z][1]==y]=x;
        ch[x][k^1]=y;ch[y][k]=w;
        if (w) fa[w]=y;fa[y]=x;fa[x]=z;
        pushup(y);pushup(x);
    }
    
    void splay(int x)
    {
        update(x);
        while (!isroot(x))
        {
            int y=find(fa[x]),z=find(fa[y]);
            if (!isroot(y))
            {
                if ((ch[z][1]==y)^(ch[y][1]==x)) rotate(x);else rotate(y);
            }
            rotate(x);
        }
        pushup(x);
    }
    
    void access(int x)
    {
        int y=0;
        while (x)
        {
            splay(x);ch[x][1]=y;pushup(x);
            y=x;fa[y]=find(fa[y]);x=find(fa[x]);
        }
    }
    
    int findroot(int x)
    {
        access(x);splay(x);
        while (ch[x][0])
        {
            pushdown(x);x=ch[x][0];
        }
        splay(x);return x;
    }
    
    void out()
    {
        cout <<endl;
        rep(i,1,n) cout << ch[i][0] << " " << ch[i][1] <<" ";cout << endl;
        cout << endl;
    }
    
    void makeroot(int x) {access(x);splay(x);puttag(x);}
    void link(int x,int y) {makeroot(x);fa[x]=y;}
    void split(int x,int y) {makeroot(x);access(y);splay(y);}
    void cut(int x,int y) {split(x,y);ch[y][0]=0;fa[x]=0;pushup(y);}
    void del(int x,int y)
    {
        f[x]=y;pushdown(x);
        if (ch[x][0]) del(ch[x][0],y);
        if (ch[x][1]) del(ch[x][1],y);
    }
    
    int main()
    {
        n=read();m=read();
        rep(i,1,n)
        {
            val[i]=read();sum[i]=val[i];w[i]=val[i];
            f[i]=i;con[i]=i;
        }
        rep(i,1,m)
        {
            int op=read(),x=read(),y=read();
            if (op==1)
            {
                int fx=find(x),fy=find(y);
                if (fx==fy) continue;
                int cx=findcon(fx),cy=findcon(fy);
                if (cx!=cy) 
                {
                    link(fx,fy);
                    con[cx]=cy;
                }
                else 
                {
                    split(fx,fy);w[fy]=sum[fy];
                    del(fy,fy);ch[fy][0]=0;pushup(fy);
                }
            }
            else if (op==2)
            {
                int fx=find(x);splay(fx);
                w[fx]+=(y-val[x]);sum[fx]+=(y-val[x]);
                val[x]=y;pushup(fx);
            }
            else if (op==3)
            {
                int fx=find(x),fy=find(y);
                int cx=findcon(fx),cy=findcon(fy);
                if (cx!=cy) puts("-1");
                else 
                {
                    split(fx,fy);
                    printf("%d
    ",sum[fy]);
             
                }
            }
        }
        return 0;
    }
    /*
    9 31
    10 20 30 40 50 60 70 80 90
    3 1 2
    1 1 3
    1 1 2
    1 8 9
    1 2 4
    1 2 5
    1 4 6
    1 4 7
    3 1 8
    3 8 8
    1 8 9
    3 8 8
    3 7 5
    3 7 3
    1 4 1
    3 7 5
    3 7 3
    1 5 7
    3 6 5
    3 3 6
    1 2 4
    1 5 5
    3 3 6
    2 8 180
    3 8 8
    2 9 190
    3 9 9
    2 5 150
    3 3 6
    2 1 210
    3 3 6
     */
    
  • 相关阅读:
    linux命令整理
    各种提权姿势总结
    常用端口信息说明和利用
    近年来爆发的CVE漏洞编号
    一个优秀的SSH远程终端工具
    python-读写文件的方式
    kali安装ssh服务
    一套实用的渗透测试岗位面试题
    使用 python快速搭建http服务
    asciinema使用
  • 原文地址:https://www.cnblogs.com/encodetalker/p/11123906.html
Copyright © 2020-2023  润新知