• bzoj 2594 [Wc2006]水管局长数据加强版


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

    据说写得丑会TLE。反正我T了好久……

    这道题时间倒流一下就是 bzoj3669魔法森林 了。

    0.我好……呀,竟然没深入想想应该是二分找到每个询问对应的边!

    *1.一开始的加边要按kruscal的方式,就要按边权排序;可为了二分还要按x、y排序。这时对于标号的处理需要费一番心机。(反正我是抄hzwer的)

    **2.query要写成 int 的,不要写成 void 的再在主函数里调用mx[后一项]。反正如果那样就会TLE!!!可能也和在makeroot里用了void的query有关?

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=1e5+5,M=1e6+5;
    int n,m,Q,fa[N],pre[N+M],val[N+M],c[N+M][2],mx[N+M],stack[N+M],top,ans[N],cnt;
    bool rev[N+M];
    struct Ed{
        int x,y,w,bh;bool vis;
        bool operator< (const Ed &k)const{return w<k.w;}
    }ed[M];
    struct Ques{
        int op,x,y,e;
    }q[N];
    int rdn()
    {
        int ret=0,fx=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')fx=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')(ret*=10)+=ch-'0',ch=getchar();
        return ret*fx;
    }
    bool cmp(Ed u,Ed v){return u.x==v.x?u.y<v.y:u.x<v.x;}
    bool cmp2(Ed u,Ed v){return u.bh<v.bh;}
    int fd(int x,int y)
    {
        int l=1,r=m,ret=0;
        while(l<=r)
        {
            int mid=((l+r)>>1);
            if(ed[mid].x>x||(ed[mid].x==x&&ed[mid].y>=y))ret=mid,r=mid-1;
            else l=mid+1;
        }
        return ret;
    }
    int find(int a){return fa[a]==a?a:fa[a]=find(fa[a]);}
    bool isroot(int x){return c[pre[x]][0]!=x&&c[pre[x]][1]!=x;}
    void pshp(int x)
    {
        mx[x]=x;
        if(val[mx[c[x][0]]]>val[mx[x]])mx[x]=mx[c[x][0]];
        if(val[mx[c[x][1]]]>val[mx[x]])mx[x]=mx[c[x][1]];
    }
    void reverse(int x)
    {
        if(rev[x]){
            rev[c[x][0]]^=1;rev[c[x][1]]^=1;
            swap(c[x][0],c[x][1]);
            rev[x]=0;
        }
    }
    void rotate(int x)
    {
        int y=pre[x],z=pre[y],d=(x==c[y][1]);
        if(!isroot(y))c[z][y==c[z][1]]=x;
        pre[x]=z;pre[y]=x;
        c[y][d]=c[x][!d];pre[c[x][!d]]=y;c[x][!d]=y;
        pshp(y);pshp(x);
    }
    void splay(int x)
    {
        stack[top=1]=x;
        for(int t=x;!isroot(t);t=pre[t])stack[++top]=pre[t];    //用t…… 
        for(;top;top--)reverse(stack[top]);
        for(;!isroot(x);rotate(x))
        {
            int y=pre[x],z=pre[y];
            if(isroot(y))continue;
            ((y==c[z][0])^(x==c[y][0]))?rotate(x):rotate(y);
        }
        pshp(x);//?
    }
    void access(int x)
    {
        for(int t=0;x;c[x][1]=t,t=x,x=pre[x])splay(x);//这里不是!isroot(x)!!! 
    }
    void makeroot(int x)
    {
        access(x);splay(x);rev[x]^=1;
    }
    void link(int x,int y)
    {
        makeroot(x);pre[x]=y;
    }
    int query(int x,int y) //当前辅助树中只有x、y之间的链!
    {
        makeroot(x);access(y);splay(y);return mx[y];
    }
    void cut(int x,int y)   //当前辅助树中只有x、y两个点!(因为取出链,但有直接边) 
    {
        makeroot(x);access(y);splay(y);
        pre[x]=0;c[y][0]=0;
    }
    int main()
    {
        n=rdn();m=rdn();Q=rdn();
        for(int i=1;i<=m;i++)
        {
            ed[i].x=rdn();ed[i].y=rdn();ed[i].w=rdn();
            if(ed[i].x>ed[i].y)swap(ed[i].x,ed[i].y);
        }
        sort(ed+1,ed+m+1);
        for(int i=1;i<=m;i++)
            ed[i].bh=i,val[i+n]=ed[i].w;
        sort(ed+1,ed+m+1,cmp);
        for(int i=1;i<=Q;i++)
        {
            q[i].op=rdn();q[i].x=rdn();q[i].y=rdn();
            if(q[i].op==1)continue;/////
            if(q[i].x>q[i].y)swap(q[i].x,q[i].y);
            int k=fd(q[i].x,q[i].y);
            q[i].e=ed[k].bh;ed[k].vis=1;
        }
        for(int i=1;i<=n;i++)fa[i]=i;
        sort(ed+1,ed+m+1,cmp2);int tot=0;
        for(int i=1;i<=m;i++) if(!ed[i].vis){
            int u=ed[i].x,v=ed[i].y;
            if(find(u)!=find(v)){
                fa[find(u)]=find(v);link(i+n,u);link(i+n,v);tot++;
                if(tot==n-1)break;
            }
        }
        for(int i=Q;i;i--)
        {
            if(q[i].op==1)ans[++cnt]=val[query(q[i].x,q[i].y)];//val[]
            else {
                int k=q[i].e,u=ed[k].x,v=ed[k].y;
                int t=query(u,v);if(val[t]<=ed[k].w)continue;
                cut(t,ed[t-n].x);cut(t,ed[t-n].y);
                link(k+n,u);link(k+n,v);
            }
        }
        for(int i=cnt;i;i--)printf("%d
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    javascript数组
    Javascript prototype理解
    Javascript中的类的创建
    Div拖动效果
    javascript, position
    getSelection();
    网页的宽和高
    javascript apply & call
    Hibernate数据丢失更新问题及解决 凡人
    招聘软件/网页UI设计师
  • 原文地址:https://www.cnblogs.com/Narh/p/9237635.html
Copyright © 2020-2023  润新知