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;
}

你可能感兴趣的:(LCT)