• bzoj2594 [Wc2006]水管局长数据加强版——LCT


    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2594

    时间倒序一下,就是 魔法森林 那道题;

    有个不解的地方,是 access 里面关于 pushup 的地方,两种写法都可以,但不明白没有注释掉的写法为什么也可以。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int const maxn=1500005,maxm=1e6+5;
    int n,m,Q,val[maxn],mx[maxn],fa[maxn],pre[maxn],c[maxn][3],sta[maxn],rev[maxn];
    struct N{int hd,to,w,id; bool b;}edge[maxm];
    struct T{int u,v,ans,f,id;}q[100005];
    bool cmp(N x,N y){return x.w<y.w;}
    bool cmp2(N x,N y){return x.hd<y.hd || (x.hd==y.hd && x.to<y.to);}
    bool cmpp(N x,N y){return x.id<y.id;}
    int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    int rd()
    {
        int ret=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
        return ret*f;
    }
    int get(int x,int y)
    {
        int l=1,r=m;
        while(l<=r)
        {
            int mid=((l+r)>>1);
            if(edge[mid].hd==x && edge[mid].to==y)return mid;
            if(edge[mid].hd<x || (edge[mid].hd==x && edge[mid].to<y))l=mid+1;
            else r=mid-1;
        }
    }
    bool isroot(int x)
    {
        return c[pre[x]][0]!=x && c[pre[x]][1]!=x;
    }
    void pushup(int x)
    {
        int ls=c[x][0],rs=c[x][1];
        mx[x]=x;
        if(val[mx[ls]]>val[mx[x]])mx[x]=mx[ls];
        if(val[mx[rs]]>val[mx[x]])mx[x]=mx[rs];
    }
    void reverse(int x)
    {
        int ls=c[x][0],rs=c[x][1];
        if(rev[x])
        {
            rev[ls]^=1; rev[rs]^=1; rev[x]=0;
            swap(c[x][0],c[x][1]);
        }
    }
    void rotate(int x)
    {
        int y=pre[x],z=pre[y],d=(c[y][1]==x);
        if(!isroot(y))c[z][c[z][1]==y]=x;
        pre[x]=z; pre[y]=x; pre[c[x][!d]]=y;
        c[y][d]=c[x][!d]; c[x][!d]=y;
        pushup(y); pushup(x);
    }
    void splay(int x)
    {
        int top=0; sta[++top]=x;
        for(int i=x;!isroot(i);i=pre[i])sta[++top]=pre[i];
        for(int i=top;i;i--)reverse(sta[i]);
        for(;!isroot(x);rotate(x))
        {
            int y=pre[x],z=pre[y];
            if(isroot(y))continue;
            ((c[y][0]==x)^(c[z][0]==y))?rotate(x):rotate(y);
        }
        pushup(x);//和下面配套 
    }
    void access(int x)
    {
        for(int t=0;x;c[x][1]=t,t=x,x=pre[x])splay(x);//这样为什么也可以? 
    }
    //void access(int x)
    //{
    //    int t=0;
    //    while(x)
    //    {
    //        splay(x);c[x][1]=t;pushup(x);t=x;x=pre[x];
    //    }
    //}
    void makeroot(int x)
    {
        access(x); splay(x); rev[x]^=1;
    }
    void link(int x,int y)
    {
        makeroot(x); pre[x]=y;//
    }
    void cut(int x,int y)
    {
        makeroot(x); access(y); splay(y);
        pre[x]=0; c[y][0]=0;
    }
    int query(int x,int y)
    {
        makeroot(x); access(y); splay(y); return mx[y];
    }
    int main()
    {
        n=rd(); m=rd(); Q=rd();
        for(int i=1;i<=n;i++)fa[i]=i;
        for(int i=1;i<=m;i++)
        {
            edge[i].hd=rd(); edge[i].to=rd(); edge[i].w=rd();
            if(edge[i].hd>edge[i].to)swap(edge[i].hd,edge[i].to);
        }
        sort(edge+1,edge+m+1,cmp);//w 
        for(int i=1;i<=m;i++)
        {
            edge[i].id=i;
            val[i+n]=edge[i].w; mx[i+n]=i+n;//
        }
        sort(edge+1,edge+m+1,cmp2);//u,v 
        for(int i=1;i<=Q;i++)
        {
            q[i].f=rd(); q[i].u=rd(); q[i].v=rd();
            if(q[i].f==2)
            {
                if(q[i].u>q[i].v)swap(q[i].u,q[i].v);
                int t=get(q[i].u,q[i].v);
    //            edge[t].b=1; q[i].id=edge[i].id;
                edge[t].b=1; q[i].id=edge[t].id;
            }
        }
        sort(edge+1,edge+m+1,cmpp);//w
        for(int i=1,tot=0;i<=m;i++)
        {
            if(edge[i].b)continue;//kruskal 连不删的边 
            int u=edge[i].hd,v=edge[i].to;
            if(find(u)!=find(v))
            {
                fa[find(u)]=find(v);
                link(u,i+n); link(v,i+n);
                tot++;
                if(tot==n-1)break;
            }
        }
        for(int i=Q;i;i--)
        {
            int u=q[i].u,v=q[i].v;
            if(q[i].f==1)q[i].ans=val[query(u,v)];
            else
            {
                int k=q[i].id,t=query(u,v);
                if(edge[k].w<val[t])
                {
                    cut(t,edge[t-n].hd); cut(t,edge[t-n].to);
                    link(u,k+n); link(v,k+n);
                }
            }
        }
        for(int i=1;i<=Q;i++)
            if(q[i].f==1)printf("%d
    ",q[i].ans);
        return 0;
    }
  • 相关阅读:
    B 合约数
    Weekly Contest 80
    第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛
    2018年长沙理工大学第十三届程序设计竞赛
    通过 DDNS 解决宽带拨号 ip 变化问题
    frp 内网穿透的使用 和原理
    笔记本centos 取消 关闭盖子自动挂起
    centos7 pptp 安装
    linux 命令收集
    centos7 关闭防护墙
  • 原文地址:https://www.cnblogs.com/Zinn/p/9240147.html
Copyright © 2020-2023  润新知