2959: 长跑|LCT+并查集

Posted ws_yzy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2959: 长跑|LCT+并查集相关的知识,希望对你有一定的参考价值。

慎入…此人代码自带5倍常数。。
静态的话就是随便搞出一棵生成树来,然后把环缩起来,询问的答案就是路径上的权值和
动态的就需要LCT来维护生成树,每遇到连起边来就形成环的情况时,就把这个环缩成一个点
动态的查询一条链上的权值和。
为什么我的代码的常数这么大…….后几个点在本地跑5s

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<ctime>
#include<queue>
#include<set>
#include<map>
#define q1 Q[T^1]
#define q2 Q[T]
#define N 1000005
using namespace std;
long long sum[N],v[N];
bool rev[N];
int fa[N],ch[N][2],n,m,dad[N],st[N];
int find(int x)

    return dad[x]==x?x:dad[x]=find(dad[x]);

void push_down(int x)

    if(rev[x])
    
        swap(ch[x][0],ch[x][1]);
        rev[ch[x][0]]^=1;
        rev[ch[x][1]]^=1;
        rev[x]=0;
    

void push_up(int x)

    sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+v[x];

bool Root(int x)

    return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;

void rotate(int x)

    int y=fa[x],z=fa[y],l,r;
    l=(ch[y][1]==x);r=l^1;
    if(!Root(y)) ch[z][ch[z][1]==y]=x;
    ch[y][l]=ch[x][r]; ch[x][r]=y;
    fa[ch[y][l]]=y;fa[y]=x;fa[x]=z;
    push_up(y); push_up(x);

void splay(int x)

    int top=0;st[++top]=x;
    for(int i=x;!Root(i);i=fa[i])st[++top]=fa[i];
    while(top)push_down(st[top--]);
    while(!Root(x))
    
        int y=fa[x],z=fa[y];
        if(!Root(y))
             if(ch[z][0]==y^ch[y][0]==x) 
                 rotate(x);
             else rotate(y);
        rotate(x);
    

void access(int x)

    for(int t=0;x;t=x,x=find(fa[x]))
    
        splay(x),ch[x][1]=t,push_up(x);
        if(t)fa[t]=x;
    
       
void make_root(int x)

    access(x),splay(x),rev[x]^=1;

void link(int x,int y)

    make_root(x),fa[x]=y;

int search(int x)

    access(x);splay(x);
    while(ch[x][0])x=ch[x][0],push_down(x);
    return x;

void dfs(int x,int f)

    if(!x)return;
    dad[x]=f;
    dfs(ch[x][0],f);
    dfs(ch[x][1],f);
   
void merge(int x,int y)

    make_root(x),access(y),splay(y);
    ++n;dad[n]=n;
    sum[n]=v[n]=sum[y];
    dfs(y,n);

int main()


    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&v[i]),dad[i]=i;
    while(m--)
    
        int opt,x,y;
        scanf("%d%d%d",&opt,&x,&y);
        if(opt==1)
        
            if(find(x)!=find(y))
            
                x=find(x),y=find(y);
                if(search(x)!=search(y))
                    link(x,y);
                else merge(x,y);
            
        
        else if(opt==2)
        
            int ch=y-v[x];
            int F=find(x);
            access(F),splay(F);
            v[F]+=ch,sum[F]+=ch;
            v[x]=y;
        
        else 
        
            if(find(x)==find(y))
                printf("%lld\\n",v[find(x)]);
            else 
            
                x=find(x),y=find(y);
                if(search(x)!=search(y))
                     puts("-1");
                else 
                
                    make_root(x);
                    access(y);
                    splay(y);
                    printf("%lld\\n",sum[y]);
                
            
        
    
    return 0;

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

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

[BZOJ2959]长跑

Bzoj2959: 长跑

bzoj2959: 长跑 LCT+并查集+边双联通

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

[BZOJ2959]长跑