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


    来自FallDream的博客,未经允许,请勿转载,谢谢。


    简要题意:给定一张n个点m条边的图,有边权,需要支持两个操作 1)删除一条边2)求两点之间边权最大值的最小值   n和操作次数不超过10^5,m<=10^6
    题解:很显然要你维护的是一个最小生成树qaq
    然后删边太难了,考虑倒过来加边,用边权lct维护最小生成树。每个点维护向父亲和偏爱儿子的连边的编号,还有他所在的splay的最左边和最右边的那条边(不懂边权lct可以自行百度)
    假设你要插入边u->v,如果它们不连通,直接插入。不然的话,如果u->v的路径上的边权的最大值超过了这条边的边权,删掉最大的那条边,加入这条边就行了。
    lct常数巨大  所以一开始把没被删除的边插入的时候不能lct,要用kruscal,不然T的飞起。
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define MN 100000
    #define INF 2000000000
    #define getchar() (*S++) 
    using namespace std;
    char B[1<<26],*S=B;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    
    int n,m,Q,rk[MN*10+5],fa[MN+5],qu[MN+5],top,c[MN+5][2],mx[MN+5],s[MN+5],p[MN+5],f[MN+5],L[MN+5],R[MN+5],ans[MN+5];
    bool rev[MN+5],mark[MN*10+5];
    struct edge{int from,to,w,num;
        bool operator<(const edge&b)const{return from==b.from?to<b.to:from<b.from;}
    }e[MN*10+5];
    struct ques{int kind,x,y;}q[MN+5];
    
    inline bool isroot(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;}
    inline void pushdown(int x)
    {
        if(rev[x])
        {
            int l=c[x][0],r=c[x][1];
            rev[l]^=1;rev[r]^=1;rev[x]^=1;
            swap(c[x][0],c[x][1]);
            swap(L[l],R[l]);swap(f[l],p[l]);
            swap(L[r],R[r]);swap(f[r],p[r]); 
        }
    }
    inline void U(int&x,int y){if(e[x].w<e[y].w) x=y;}
    inline void update(int x)
    {
        mx[x]=(e[f[x]].w>e[p[x]].w)?f[x]:p[x];
        L[x]=f[x];R[x]=p[x];
        int l=c[x][0],r=c[x][1];
        if(l) L[x]=L[l],U(mx[x],mx[l]),U(mx[x],p[l]);
        if(r) R[x]=R[r],U(mx[x],mx[r]),U(mx[x],f[r]); 
    }
    
    void rotate(int x)
    {
        int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1;
        if(!isroot(y)) c[z][c[z][1]==y]=x;
        fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
        c[y][l]=c[x][r];c[x][r]=y;
        update(y);update(x);
    }
    
    void splay(int x)
    {
        qu[top=1]=x;
        for(int t=x;!isroot(t);t=fa[t]) qu[++top]=fa[t];
        for(;top;--top) pushdown(qu[top]);
        for(;!isroot(x);rotate(x))
            if(!isroot(fa[x])) rotate((c[fa[fa[x]]][1]==fa[x]^c[fa[x]][1]==x)?x:fa[x]);
    }
    
    void access(int x)
    {
        for(int y=0;x;x=fa[y=x])
            splay(x),c[x][1]=y,p[x]=L[y],update(x);
    }
    
    void link(int x,int y,int z)
    {
        access(x);splay(x);rev[x]^=1;swap(f[x],p[x]);swap(L[x],R[x]); 
        access(y);fa[c[y][1]=x]=y;f[x]=p[y]=z;
        update(x);update(y);
    }
    
    void cut(int x,int y)
    {
        access(x);splay(x);rev[x]^=1;swap(f[x],p[x]);swap(L[x],R[x]); 
        access(y);splay(y);c[y][0]=fa[x]=f[y]=p[x]=0;
        update(x);update(y);
    }
    
    void ins(int id)
    {
        int x=e[id].from,y=e[id].to,z=e[id].w;
        access(x);splay(x);rev[x]^=1;swap(f[x],p[x]);swap(L[x],R[x]); 
        access(y);splay(y);
        if(isroot(x)) link(x,y,id);
        else if(e[mx[y]].w>z) cut(e[mx[y]].from,e[mx[y]].to),link(x,y,id);
    }
    
    inline int getfa(int x){return !s[x]?x:s[x]=getfa(s[x]);}
    bool cmp(int x,int y){return e[x].w<e[y].w;}
    int main()
    {
        fread(B,1,1<<26,stdin);
        e[0].w=-INF;
        n=read();m=read();Q=read();
        for(register int i=1;i<=m;i++) 
        {
            e[i].from=read(),e[i].to=read(),e[i].w=read();
            if(e[i].from>e[i].to) swap(e[i].from,e[i].to);
        }
        sort(e+1,e+m+1);
        for(int i=1;i<=m;i++) rk[i]=i;
        for(register int i=1;i<=Q;i++)
        {
            q[i].kind=read();q[i].x=read();q[i].y=read();
            if(q[i].kind==2) 
            {
                if(q[i].x>q[i].y) swap(q[i].x,q[i].y);
                q[i].x=lower_bound(e+1,e+m+1,(edge){q[i].x,q[i].y,0})-e;    
                mark[q[i].x]=1;
            }
        }
        sort(rk+1,rk+m+1,cmp);
        for(register int i=1;i<=m;i++)
            if(!mark[rk[i]])
            {
                int x=getfa(e[rk[i]].from),y=getfa(e[rk[i]].to);
                if(x!=y) s[x]=y,link(e[rk[i]].from,e[rk[i]].to,rk[i]);
            }
        for(register int i=Q;i;i--)
            if(q[i].kind==2) ins(q[i].x);
            else
            {
                int x=q[i].x,y=q[i].y;
                access(x);splay(x);rev[x]^=1;swap(f[x],p[x]);swap(L[x],R[x]); 
                access(y);splay(y);
                ans[i]=e[mx[y]].w;
            }
        for(register int i=1;i<=Q;i++)
            if(q[i].kind<2) printf("%d
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    [编写高质量代码:改善java程序的151个建议]建议72 生成字列表后不要再操作原列表
    [编写高质量代码:改善java程序的151个建议]建议71 推荐使用subList处理局部列表
    [编写高质量代码:改善java程序的151个建议]建议70 子列表只是原列表的一个视图
    程序员的简历到底该怎么写?(转)
    SQL数据库数据优化SQL优化总结( 百万级数据库优化方案)
    sqlserver的四种分页方式
    sql server中截取字符串的常用函数(自己经常到用的时候想不起来所以拿到这里)
    SQL之存储过程详细介绍及语法(篇幅比较长慢慢看)
    超经典SQL练习题,做完这些你的SQL就过关了
    SqlServer 数据库引擎优化顾问优化数据库(消耗内存很大)
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj2594.html
Copyright © 2020-2023  润新知