zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    网络安全分析
    java实现 洛谷 P1464 Function
    java实现 洛谷 P1464 Function
    java实现 洛谷 P1014 Cantor表
    java实现 洛谷 P1014 Cantor表
    java实现 洛谷 P1014 Cantor表
    java实现 洛谷 P1014 Cantor表
    java实现 洛谷 P1014 Cantor表
    java实现 洛谷 P1540 机器
    java实现 洛谷 P1540 机器
  • 原文地址:https://www.cnblogs.com/Zinn/p/9240147.html
Copyright © 2011-2022 走看看