zoukankan      html  css  js  c++  java
  • BZOJ 3514: Codechef MARCH14 GERALD07加强版 [LCT 主席树 kruskal]

    3514: Codechef MARCH14 GERALD07加强版

    Time Limit: 60 Sec  Memory Limit: 256 MB
    Submit: 1312  Solved: 501
    [Submit][Status][Discuss]

    Description

    N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数。

    Input

    第一行四个整数N、M、K、type,代表点数、边数、询问数以及询问是否加密。
    接下来M行,代表图中的每条边。
    接下来K行,每行两个整数L、R代表一组询问。对于type=0的测试点,读入的L和R即为询问的L、R;对于type=1的测试点,每组询问的L、R应为L xor lastans和R xor lastans。

    Output

     K行每行一个整数代表该组询问的联通块个数。

    Sample Input

    3 5 4 0
    1 3
    1 2
    2 1
    3 2
    2 2
    2 3
    1 5
    5 5
    1 2

    Sample Output

    2
    1
    3
    1

    HINT

    对于100%的数据,1≤N、M、K≤200,000。

    2016.2.26提高时限至60s

    Source

    By zhonghaoxi


    刚刚去看了CreationAugust的Blog,感觉好伤感,也许我的未来就是这样吧

    这道题好神啊

    LCT维护动态最小生成树,先将每条边依次加进去,若形成环弹掉最早加进去的边,然后记录early[]数组,表示第i条边弹掉了哪条边,若没有弹出边,early[i]=0
    然后每个询问的答案就是用n减掉[l,r]区间内ntr值小于l的边的数量 可以用主席树来维护
    注意有自环

    early[i]数组记录的边不算的话i就可以贡献一个连通分量了,所以这样做

    又调了好长时间,最后发现主席树挂掉了因为以前写顺手了虽然是mid=(l+r)>>1但还是用了m...............RE一片

    最后说一下一道题用了多个大数据结构怎么办:

    1.可以用namespace

    2.宏定义是可以取消的,#undef 名字

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    #define pa t[x].fa
    #define lc t[x].ch[0]
    #define rc t[x].ch[1]
    const int N=2e5+5;
    typedef long long ll;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    int n,m,Q,type;
    struct LCTnode{
        int ch[2],fa,rev,w,mx,p;
    }t[N<<1];
    inline int wh(int x){return t[pa].ch[1]==x;}
    inline int isRoot(int x){return t[pa].ch[0]!=x&&t[pa].ch[1]!=x;}
    inline void update(int x){
        t[x].mx=t[x].w;t[x].p=x;
        if(t[lc].mx>t[x].mx) t[x].mx=t[lc].mx,t[x].p=t[lc].p;
        if(t[rc].mx>t[x].mx) t[x].mx=t[rc].mx,t[x].p=t[rc].p;
    }
    inline void rever(int x){
        t[x].rev^=1;
        swap(lc,rc);
    }
    inline void pushDown(int x){
        if(t[x].rev){
            rever(lc);
            rever(rc);
            t[x].rev=0;    
        }
    }
    inline void rotate(int x){
        int f=t[x].fa,g=t[f].fa,c=wh(x);
        if(!isRoot(f)) t[g].ch[wh(f)]=x;t[x].fa=g;
        t[f].ch[c]=t[x].ch[c^1];t[t[f].ch[c]].fa=f;
        t[x].ch[c^1]=f;t[f].fa=x;
        update(f);update(x);
    }
    int st[N],top;
    inline void splay(int x){
        top=0;st[++top]=x;
        for(int i=x;!isRoot(i);i=t[i].fa) st[++top]=t[i].fa;
        for(int i=top;i>=1;i--) pushDown(st[i]);
        
        for(;!isRoot(x);rotate(x))
            if(!isRoot(pa)) rotate(wh(x)==wh(pa)?pa:x);
    }
    inline void Access(int x){
        for(int y=0;x;y=x,x=pa){
            splay(x);
            rc=y;
            update(x);
        }
    }
    inline void MakeR(int x){
        Access(x);splay(x);
        rever(x);
    }
    inline int FindR(int x){
        Access(x);splay(x);
        while(lc) x=lc;
        return x;
    }
    inline void Link(int x,int y){
        MakeR(x);
        t[x].fa=y;
    }
    inline void Cut(int x,int y){
        MakeR(x);Access(y);splay(y);
        t[y].ch[0]=t[x].fa=0;
        update(y);//!!!
    }
    inline void Split(int x,int y){
        MakeR(x);Access(y);splay(y);
    }
    inline int Que(int x,int y){
        MakeR(x);Access(y);splay(y);
        return t[y].p;
    }
    
    struct edge{
        int u,v;
    }e[N];
    int early[N];
    void Kruskal(){
        for(int i=1;i<=m;i++){//printf("kru %d
    ",i);
            int u=e[i].u,v=e[i].v;
            if(u==v) {early[i]=i;continue;}
            if(FindR(u)==FindR(v)){
                int p=Que(u,v);
                early[i]=p-n;
                Cut(e[p-n].u,p);Cut(e[p-n].v,p);
            }
            Link(u,i+n);Link(v,i+n);
        }
    }
    
    #undef lc
    #undef rc
    #define lc(x) t[x].l
    #define rc(x) t[x].r
    namespace F{
        struct Fnode{
            int l,r,size;
        }t[N*30];
        int sz=0,root[N];
        void ins(int &x,int l,int r,int p){
            t[++sz]=t[x]; x=sz;
            t[x].size++;
            if(l==r) return;
            int mid=(l+r)>>1;
            if(p<=mid) ins(t[x].l,l,mid,p);
            else ins(t[x].r,mid+1,r,p);
        }
        int que(int x,int y,int l,int r,int ql,int qr){//printf("que %d %d %d %d
    ",l,r,ql,qr);
            if(ql<=l&&r<=qr) return t[y].size-t[x].size;
            else{
                int m=(l+r)>>1,ans=0;
                if(ql<=m) ans+=que(lc(x),lc(y),l,m,ql,qr);
                if(m<qr) ans+=que(rc(x),rc(y),m+1,r,ql,qr);
                return ans;
            }
        }
        int l,r,lastans=0;
        void solve(){
            for(int i=1;i<=m;i++) root[i]=root[i-1],ins(root[i],0,m,early[i]);
            //for(int i=0;i<=m;i++) printf("root %d
    ",root[i]); 
            while(Q--){
                l=read();r=read();
                if(type) l^=lastans,r^=lastans;
                lastans=n-que(root[l-1],root[r],0,m,0,l-1);
                printf("%d
    ",lastans);
            }
        }
    }
    int main(){
        //freopen("in.txt","r",stdin);
        n=read();m=read();Q=read();type=read();
        for(int i=1;i<=m;i++){
            e[i].u=read(),e[i].v=read();
            t[i+n].w=t[i+n].mx=m+n-i+1;
            t[i+n].p=i+n;
        }
        Kruskal();
        F::solve();
    }

     

  • 相关阅读:
    Java学习笔记8(面向对象3:接口)
    面向对象2(继承,抽象类)
    java学习笔记6(面向对象1:概念,private)
    排序方法-循环和数组练习
    ArrayList方法综合练习
    Eclipse的配置
    集合(ArrayList)简述
    java学习笔记5(方法)
    数据结构9——最小生成树
    数据结构8——图的遍历
  • 原文地址:https://www.cnblogs.com/candy99/p/6279791.html
Copyright © 2011-2022 走看看