zoukankan      html  css  js  c++  java
  • BZOJ 2594: [Wc2006]水管局长数据加强版

    突然回想起之前板刷了LCT题单的,那么不是意味着LCT都不用写了么233

    这题还算比较简单且套路,最大值最小想到维护原图的最小生成树,这里用LCT维护

    那么删边太麻烦了,我们离线之后倒着做,把删除改成插入

    那么对于新加入的一条边,显然我们把它的边权和本来两点间的路径上的边权最大边进行对比一下看看是否要替换即可

    PS:花了30min才复习完了LCT板子,发现我的水平急剧下降,记得当时可以10min写出LCT的,现在……

    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    #define RI register int
    #define CI const int&
    #define Tp template <typename T>
    using namespace std;
    const int N=100005,M=1000005;
    struct edge
    {
        int x,y,v,id; bool iscut;
    }e[M]; int n,m,q_tot,ans[N];
    struct ques
    {
        int opt,x,y,id;
    }q[N]; int val[N+M];
    inline bool cmpx(const edge& A,const edge& B)
    {
        return A.x<B.x||(A.x==B.x&&A.y<B.y);
    }
    inline bool cmpv(const edge& A,const edge& B)
    {
        return A.v<B.v;
    }
    inline bool cmpid(const edge& A,const edge& B)
    {
        return A.id<B.id;
    }
    class FileInputOutput
    {
        private:
            static const int S=1<<21;
            #define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
            #define pc(ch) (Ftop<S?Fout[Ftop++]=ch:(fwrite(Fout,1,S,stdout),Fout[(Ftop=0)++]=ch))
            char Fin[S],Fout[S],*A,*B; int Ftop,pt[15];
        public:
            Tp inline void read(T& x)
            {
                x=0; char ch; while (!isdigit(ch=tc()));
                while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
            }
            Tp inline void write(T x)
            {
                if (!x) return (void)(pc('0'),pc('
    ')); RI ptop=0;
                while (x) pt[++ptop]=x%10,x/=10; while (ptop) pc(pt[ptop--]+48); pc('
    ');
            }
            inline void Fend(void)
            {
                fwrite(Fout,1,Ftop,stdout);
            }
            #undef tc
            #undef pc
    }F;
    inline void swap(int& x,int& y)
    {
        int t=x; x=y; y=t;
    }
    inline int find(CI x,CI y)
    {
        int l=1,r=m,mid; while (l<=r)
        {
            mid=l+r>>1; if (e[mid].x==x&&e[mid].y==y) return mid;
            if (e[mid].x<x||(e[mid].x==x&&e[mid].y<y)) l=mid+1; else r=mid-1;
        }
    }
    class Link_Cut_Tree
    {
        private:
            struct splay
            {
                int ch[2],fa,mx; bool rev;
            }node[N+M]; int stack[N+M],top;
            #define lc(x) node[x].ch[0]
            #define rc(x) node[x].ch[1]
            #define fa(x) node[x].fa
            #define mx(x) node[x].mx
            inline void rever(CI now)
            {
                swap(lc(now),rc(now)); node[now].rev^=1;
            }
            inline void pushup(CI now)
            {
                mx(now)=now; if (val[mx(lc(now))]>val[mx(now)]) mx(now)=mx(lc(now));
                if (val[mx(rc(now))]>val[mx(now)]) mx(now)=mx(rc(now));
            }
            inline void pushdown(CI now)
            {
                if (node[now].rev) rever(lc(now)),rever(rc(now)),node[now].rev=0;
            }
            inline int identify(CI now)
            {
                return rc(fa(now))==now;
            }
            inline void connect(CI x,CI y,CI d)
            {
                node[fa(x)=y].ch[d]=x;
            }
            inline bool isroot(CI now)
            {
                return lc(fa(now))!=now&&rc(fa(now))!=now;
            }
            inline void rotate(CI now)
            {
                int x=fa(now),y=fa(x),d=identify(now); if (!isroot(x)) node[y].ch[identify(x)]=now;
                fa(now)=y; connect(node[now].ch[d^1],x,d); connect(x,now,d^1); pushup(x); pushup(now);
            }
            inline void splay(CI now)
            {
                int t=now; while (stack[++top]=t,!isroot(t)) t=fa(t);
                while (top) pushdown(stack[top--]); for (;!isroot(now);rotate(now))
                t=fa(now),!isroot(t)&&(rotate(identify(now)!=identify(t)?now:t),0);
            }
            inline void access(int x)
            {
                for (int y=0;x;x=fa(y=x)) splay(x),rc(x)=y,pushup(x);
            }
            inline int findroot(int now)
            {
                access(now); splay(now); for (;lc(now);now=lc(now)) pushdown(now); return splay(now),now;
            }
            inline void makeroot(CI now)
            {
                access(now); splay(now); rever(now);
            }
            inline void split(CI x,CI y)
            {
                makeroot(x); access(y); splay(y);
            }
        public:
            inline void insert(CI x,CI y)
            {
                val[x]=y; node[x].mx=x;
            }
            inline void link(CI x,CI y)
            {
                makeroot(x); splay(x); if (findroot(y)!=x) fa(x)=y;
            }
            inline void cut(CI x,CI y)
            {
                makeroot(x); splay(y); if (findroot(y)==x&&fa(y)==x&&!lc(y)) rc(x)=fa(y)=0,pushup(x);
            }
            inline int query(CI x,CI y)
            {
                return split(x,y),node[y].mx;
            }
            #undef lc
            #undef rc
            #undef fa
            #undef mx
    }LCT;
    class UnionFindSet
    {
        private:
            int father[N],size[N];
            inline int getfather(CI x)
            {
                return father[x]!=x?father[x]=getfather(father[x]):x;
            }
        public:
            inline void init(void)
            {
                for (RI i=1;i<=n;++i) father[i]=i,size[i]=1;
            }
            inline bool identify(CI x,CI y)
            {
                return getfather(x)==getfather(y);
            }
            inline void Union(CI x,CI y,CI id)
            {
                int fx=getfather(x),fy=getfather(y);
                LCT.link(n+id,x); LCT.link(n+id,y);
                if (size[fx]<size[fy]) swap(fx,fy);
                size[fx]+=size[fx]==size[fy]; father[fy]=fx; size[fy]=0;
            }
    }S;
    int main()
    {
        //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
        RI i; for (F.read(n),F.read(m),F.read(q_tot),i=1;i<=m;++i)
        {
            F.read(e[i].x); F.read(e[i].y); F.read(e[i].v);
            if (e[i].x>e[i].y) swap(e[i].x,e[i].y);
        }
        for (sort(e+1,e+m+1,cmpv),i=1;i<=m;++i) e[i].id=i,LCT.insert(n+i,e[i].v);
        for (sort(e+1,e+m+1,cmpx),i=1;i<=q_tot;++i)
        {
            F.read(q[i].opt); F.read(q[i].x); F.read(q[i].y);
            if (q[i].opt==1) continue; if (q[i].x>q[i].y) swap(q[i].x,q[i].y);
            int pos=find(q[i].x,q[i].y); e[pos].iscut=1; q[i].id=e[pos].id;
        }
        for (sort(e+1,e+m+1,cmpid),S.init(),i=1;i<=m;++i)
        if (!e[i].iscut&&!S.identify(e[i].x,e[i].y)) S.Union(e[i].x,e[i].y,i);
        for (i=q_tot;i;--i)
        {
            if (q[i].opt==1) { ans[i]=val[LCT.query(q[i].x,q[i].y)]; continue; }
            int pos=LCT.query(q[i].x,q[i].y); if (e[q[i].id].v<val[pos])
            LCT.cut(e[pos-n].x,pos),LCT.cut(e[pos-n].y,pos),LCT.link(q[i].x,n+q[i].id),LCT.link(q[i].y,n+q[i].id);
        }
        for (i=1;i<=q_tot;++i) if (q[i].opt==1) F.write(ans[i]); return F.Fend(),0;
    }
    
  • 相关阅读:
    数据类面试题
    java二进制文件复制
    String源码
    集合类题目
    OBJ-C
    java文件(文件夹)操作
    java中输入方式Scanner和BufferedReader
    二次分发举例
    Eclipse常用快捷键
    c#获取新浪微博登录cookie
  • 原文地址:https://www.cnblogs.com/cjjsb/p/12242657.html
Copyright © 2011-2022 走看看