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\n",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
 */
posted @ 2019-07-02 23:54  EncodeTalker  阅读(228)  评论(0编辑  收藏  举报