• BZOJ_3514_Codechef MARCH14 GERALD07加强版_主席树+LCT


    BZOJ_3514_Codechef MARCH14 GERALD07加强版_主席树+LCT

    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。


     把这m条边按顺序插进去,维护边的编号最小的边的编号。

    当出现两个点连通时把路径上编号最小的删掉,并记录下每条边删除的时间t。

    对于询问l~r,假设这些边放进去,也会有一些边被删除。

    连通块个数=n-((r-l+1)-被删除的边数)。

    然后知道被删除的边数刚好是t小于等于r的那些边,主席树查一下即可。

    代码:

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define N 400050
    #define ls ch[p][0]
    #define rs ch[p][1]
    #define get(x) (ch[f[x]][1]==x)
    int ch[N][2],f[N],rev[N],n,m,k,siz[N*30],t[N],val[N],mx[N],tot,cnt,lson[N*30],rson[N*30];
    int xx[N],yy[N],root[N];
    inline bool isrt(int p) {
        return ch[f[p]][0]!=p&&ch[f[p]][1]!=p;
    }
    inline void pushup(int p) {
        mx[p]=p;
        if(val[mx[ls]]>val[mx[p]]) mx[p]=mx[ls];
        if(val[mx[rs]]>val[mx[p]]) mx[p]=mx[rs];
    }
    inline void pushdown(int p) {
        if(rev[p]) {
            swap(ch[ls][0],ch[ls][1]); swap(ch[rs][0],ch[rs][1]);
            rev[ls]^=1; rev[rs]^=1; rev[p]=0;
        }
    }
    void update(int p) {
        if(!isrt(p)) update(f[p]); pushdown(p);
    }
    void rotate(int x) {
        int y=f[x],z=f[y],k=get(x);
        if(!isrt(y)) ch[z][ch[z][1]==y]=x;
        ch[y][k]=ch[x][!k]; f[ch[y][k]]=y;
        ch[x][!k]=y; f[y]=x; f[x]=z;
        pushup(y); pushup(x);
    }
    void splay(int x) {
        update(x);
        for(int d;d=f[x],!isrt(x);rotate(x))
            if(!isrt(d))
                rotate(get(d)==get(x)?d:x);
    }
    void access(int p) {
        int t=0;
        while(p) splay(p),rs=t,pushup(p),t=p,p=f[p];
    }
    void makeroot(int p) {
        access(p); splay(p); swap(ls,rs); rev[p]^=1;
    }
    void link(int x,int p) {
        makeroot(x); splay(p); f[x]=p;
    }
    void cut(int x,int p) {
        makeroot(x); access(p); splay(p); ls=f[x]=0;
    }
    int find(int p) {
        access(p); splay(p); while(ls) pushdown(p),p=ls;
        return p;
    }
    void insert(int &y,int x,int l,int r,int v) {
        y=++tot; siz[y]=siz[x]+1;
        if(l==r) return ;
        int mid=(l+r)>>1;
        if(v<=mid) rson[y]=rson[x],insert(lson[y],lson[x],l,mid,v);
        else lson[y]=lson[x],insert(rson[y],rson[x],mid+1,r,v);
    }
    int query(int x,int y,int l,int r,int k) {
        if(k>=r) return siz[x]-siz[y];
        int mid=(l+r)>>1,re=0;
        if(1<=mid) re+=query(lson[x],lson[y],l,mid,k);
        if(k>mid) re+=query(rson[x],rson[y],mid+1,r,k);
        return re;
    }
    int inq(int x,int p) {
        makeroot(x); access(p); splay(p); return mx[p];
    }
    int main() {
        int type;
        scanf("%d%d%d%d",&n,&m,&k,&type);
        int i,x,y;
        cnt=n;
        for(i=1;i<=n;i++) mx[i]=i;
        for(i=1;i<=m;i++) {
            cnt++;
            scanf("%d%d",&x,&y); xx[cnt]=x; yy[cnt]=y;
            if(x==y) {
                t[i]=i; continue;
            }
            int t1=find(x),t2=find(y);
            if(t1!=t2) {
                val[cnt]=m-i+1; mx[cnt]=cnt;
                link(x,cnt); link(cnt,y);
            }else {
                val[cnt]=m-i+1; mx[cnt]=cnt;
                int d=inq(x,y); 
                //printf("%d
    ",val[d]);
                t[m-val[d]+1]=i;
                 
                cut(xx[d],d); cut(d,yy[d]);
                link(x,cnt); link(cnt,y);
            }
        }
        for(i=1;i<=m;i++) {
            if(!t[i]) t[i]=m+1;
            insert(root[i],root[i-1],1,m+1,t[i]);
        }
        int ans=0;
        while(k--) {
            scanf("%d%d",&x,&y);
            if(!type) ans=0;
            x^=ans; y^=ans;
            ans=n-y+x-1+query(root[y],root[x-1],1,m+1,y);
            printf("%d
    ",ans);
        }
        //for(i=1;i<=m;i++) printf("%d
    ",t[i]);
     
    }
    
  • 相关阅读:
    JavaScript中弧度和角度的转换
    HTML <meta> Attribute
    rel 属性<small>H5保留属性</small>
    React学习笔记
    React学习笔记
    jQuery插件制作
    jQuery ajax
    js数据存贮之数组与json
    列表与表格的一些学习
    18-10-16学习内容总结
  • 原文地址:https://www.cnblogs.com/suika/p/8968008.html
Copyright © 2020-2023  润新知