bzoj 2959: 长跑

Posted encodetalker

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
 */

以上是关于bzoj 2959: 长跑的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 2959 长跑(LCT+BCC+并查集)

bzoj2959: 长跑

Bzoj2959: 长跑

刷题BZOJ 2959 长跑

[BZOJ2959]长跑

BZOJ2959长跑(Link-Cut Tree,并查集)