zoukankan      html  css  js  c++  java
  • bzoj2594 [Wc2006]水管局长数据加强版 离线+LCT维护边权

    LCT维护边权势把每条边都当成一个点赋予点权,原来的点当然也保留,如果求和点权赋为0,求max点权赋为-INF,如果都要求,那就弄两三个点权。

    需要注意的是,LCT的link操作必须换根,如果不把x设为根而直接pre[x]=y的话,结果并不是连接x和y而是连接x的splay的根和y。在弹飞绵羊的题中之所以不用换根是因为x本来就是根。

    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    
    using namespace std;
    
    typedef long long ll;
    const int maxn=1500100;
    const int INF=1e9+10;
    
    int getint()
    {
        char ch=getchar();
        for(;ch>'9'||ch<'0';ch=getchar());
        int tmp=0;
        for(;'0'<=ch&&ch<='9';ch=getchar())
        tmp=tmp*10+int(ch)-48;
        return tmp;
    }
    
    int n,m,qn;
    struct Edge
    {
        int u,v,w;
        bool e;
        friend bool operator<(Edge A,Edge B)
        {
            return A.u==B.u?A.v<B.v:A.u<B.u;
        }
    };Edge e[maxn];
    struct Query
    {
        int op,x,y;
    };Query q[maxn];
    int pre[maxn],ch[maxn][2],rev[maxn];
    struct Node
    {
        int w,id;
        friend bool operator<(Node A,Node B)
        {
            return A.w<B.w;
        }
    };Node val[maxn],Max[maxn];
    int fa[maxn];
    int u,v,w;
    int op,x,y;
    int ans[maxn],cnt;
    
    bool cmp(Edge A,Edge B)
    {
        return A.w<B.w;
    }
    
    int bin(int l,int r,int x,int y)
    {
        int res=l;
        while(l<=r){
            int m=(l+r)>>1;
            if(e[m].u==x&&e[m].v==y) return m;
            if(x>e[m].u||(x==e[m].u&&y>e[m].v)) l=m+1;
            else r=m-1;
        }
    }
    
    int find(int x)
    {
        return fa[x]==x?x:fa[x]=find(fa[x]);
    }
    
    bool isroot(int x)
    {
        return ch[pre[x]][0]!=x&&ch[pre[x]][1]!=x;
    }
    
    void update_rev(int x)
    {
        if(!x) return;
        swap(ch[x][0],ch[x][1]);
        rev[x]^=1;
    }
    
    void up(int x)
    {
        Max[x]=max(val[x],max(Max[ch[x][0]],Max[ch[x][1]]));
    }
    
    void down(int x)
    {
        if(rev[x]){
            update_rev(ch[x][0]);
            update_rev(ch[x][1]);
            rev[x]=0;
        }
    }
    
    void Pd(int x)
    {
        if(!isroot(x)) Pd(pre[x]);
        down(x);
    }
    
    void rot(int x,int kind)
    {
        int y=pre[x];
        ch[y][kind^1]=ch[x][kind];
        pre[ch[x][kind]]=y;
        if(!isroot(y)) ch[pre[y]][ch[pre[y]][1]==y]=x;
        pre[x]=pre[y];
        ch[x][kind]=y;
        pre[y]=x;
        up(y);
    }
    
    void splay(int x)
    {
        Pd(x);
        while(!isroot(x)){
            if(isroot(pre[x])) rot(x,ch[pre[x]][0]==x);
            else{
                int y=pre[x],z=pre[y];
                int kind=ch[y][0]==x,one=0;
                if(ch[y][0]==x&&ch[z][0]==y) one=1;
                if(ch[y][1]==x&&ch[z][1]==y) one=1;
                if(one) rot(y,kind),rot(x,kind);
                else rot(x,kind),rot(x,kind^1);
            }
        }
        up(x);
    }
    
    int access(int x)
    {
        int t=0;
        while(x){
            splay(x);
            ch[x][1]=t;
            t=x;x=pre[x];
            up(t);
        }
        return t;
    }
    
    void makeroot(int x)
    {
        access(x);
        splay(x);
        update_rev(x);
    }
    
    void link(int x,int y)
    {
        makeroot(x);
        pre[x]=y;
    }
    
    void cut(int x,int y)
    {
        makeroot(x);
        access(y);
        splay(y);
        ch[y][0]=pre[x]=0;
    }
    
    Node query(int x,int y)
    {
        makeroot(x);
        access(y);
        splay(y);
        return Max[y];
    }
    
    int main()
    {
        freopen("in.txt","r",stdin);
        while(~scanf("%d%d%d",&n,&m,&qn)){
            REP(i,1,n) fa[i]=i;
            REP(i,1,m){
                u=getint();v=getint();w=getint();
                if(u>v) swap(u,v);
                e[i]={u,v,w,1};
            }
            sort(e+1,e+m+1);
            REP(i,1,qn){
                op=getint();x=getint();y=getint();
                if(x>y) swap(x,y);
                q[i]={op,x,y};
                if(op==2){
                    int k=bin(1,m,x,y);
                    e[k].e=0;
                }
            }
            sort(e+1,e+m+1,cmp);
            REP(i,1,m){
                if(e[i].e==0) continue;
                x=find(e[i].u),y=find(e[i].v);
                if(x==y) e[i].e=0;
                else fa[x]=y;
            }
            sort(e+1,e+m+1);
            REP(i,0,n+m) pre[i]=rev[i]=0,MS0(ch[i]),val[i]={-INF,i},Max[i]={-INF,i};
            REP(i,1,m){
                if(e[i].e==0) continue;
                x=e[i].u,y=e[i].v,w=e[i].w;
                val[n+i].w=Max[n+i].w=w;
                link(x,n+i);
                link(y,n+i);
            }
            Node tmp;int xx,yy;cnt=0;
            for(int i=qn;i>=1;i--){
                op=q[i].op,x=q[i].x,y=q[i].y;
                tmp=query(x,y);
                if(op==1) ans[++cnt]=tmp.w;
                else{
                    int k=bin(1,m,x,y);
                    if(e[k].w<tmp.w){
                        xx=e[tmp.id-n].u,yy=e[tmp.id-n].v;
                        cut(tmp.id,xx);
                        cut(tmp.id,yy);
                        pre[n+k]=rev[n+k]=0;MS0(ch[n+k]);
                        val[n+k]=Max[n+k]={e[k].w,n+k};
                        link(x,n+k);
                        link(y,n+k);
                    }
                }
            }
            for(int i=cnt;i>=1;i--) printf("%d
    ",ans[i]);
        }
        return 0;
    }
    View Code
    没有AC不了的题,只有不努力的ACMER!
  • 相关阅读:
    hdu2860 并查集模拟
    hdu 3938 Portal离线并查集
    hdu 2489 Minimal Ratio Tree (DFS枚举+MST)
    hdu 3172 并查集+map
    hdu 1829 A Bug's Life 并查集系列
    hdu 1598 find the most comfortable road
    HDU1198
    【Oracle】【17】表创建后,对表进行操作(添加字段,删除主键约束等)
    【JS】【19】使用Jquery判断是电脑或手机或微信浏览器访问
    【JS】【18】当前时间加减一天和格式化时间格式
  • 原文地址:https://www.cnblogs.com/--560/p/5234601.html
Copyright © 2011-2022 走看看