zoukankan      html  css  js  c++  java
  • 【LCT+主席树】BZOJ3514 Codechef MARCH14 GERALD07加强版

    3514: Codechef MARCH14 GERALD07加强版

    Time Limit: 60 Sec  Memory Limit: 256 MB
    Submit: 2023  Solved: 778
    [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

    题解

    这道题是一道思路好题(废话)

    我们可以维护每条边关于加入时间的最大生成树

    然后如果弹出一条边,记录这条边被谁弹出

    然后显然对于区间 [l,r] ti 大于 r 的边一定不会被删除

    并且所有 ti 小于等于 r 的边一定被删除

    因为 ti 小于等于 r 的边一定在一个所有边编号都小于等于 r 并且都大

    所以这段区间的答案为n-区间内大于r的数的个数

    可持久化权值线段树维护下

    代码

    //by 减维
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<bitset>
    #include<set>
    #include<cmath>
    #include<vector>
    #include<set>
    #include<map>
    #include<ctime>
    #include<algorithm>
    #define ll long long
    #define il inline
    #define rg register
    #define db double
    #define inf (1<<30)
    #define maxn 400005
    #define mpr make_pair
    #define eps 1e-8
    using namespace std;
    
    inline int read()
    {
        int ret=0;bool fla=0;char ch=getchar();
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        if(ch=='-'){fla=1;ch=getchar();}
        while(ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();}
        return fla?-ret:ret;
    }
    
    struct edge{
        int x,y;
    }e[maxn];
    
    struct tree{
        int l,r,v;
    }t[maxn<<5];
    
    int n,m,q,tt,ans,cnt,rt[maxn],fa[maxn],son[maxn][2],val[maxn],rev[maxn],pos[maxn],tim[maxn];
    
    il bool pdp(int x){return son[fa[x]][1]==x;}
    il bool isrt(int x){return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;}
    il void rever(int x){rev[x]^=1;swap(son[x][0],son[x][1]);}
    
    il void upda(int x)
    {
        pos[x]=x;
        if(son[x][0]&&val[pos[son[x][0]]]<val[pos[x]]) pos[x]=pos[son[x][0]];
        if(son[x][1]&&val[pos[son[x][1]]]<val[pos[x]]) pos[x]=pos[son[x][1]];
    }
    
    il void pdn(int x)
    {
        if(rev[x])
        {
            if(son[x][0]) rever(son[x][0]);
            if(son[x][1]) rever(son[x][1]);
            rev[x]=0;
        }
    }
    
    void pd(int x){if(!isrt(x)) pd(fa[x]);pdn(x);}
    
    il void rot(int x)
    {
        int f=fa[x],g=fa[f],o=pdp(x);
        if(!isrt(f)) son[g][pdp(f)]=x;fa[x]=g;
        son[f][o]=son[x][!o];fa[son[f][o]]=f;
        son[x][!o]=f;fa[f]=x;
        upda(f),upda(x);
    }
    
    il void splay(int x)
    {
        pd(x);
        for(;!isrt(x);rot(x))
            if(!isrt(fa[x])) rot(pdp(fa[x])==pdp(x)?fa[x]:x);
    }
    
    il void acc(int x)
    {
        for(int y=0;x;y=x,x=fa[x])
            splay(x),son[x][1]=y,upda(x);
    }
    
    il int find(int x)
    {
        acc(x);splay(x);
        while(son[x][0]) pd(x),x=son[x][0];
        return x;
    }
    
    il void bert(int x){acc(x);splay(x);rever(x);}
    il void spli(int x,int y){bert(x);acc(y);splay(y);}
    il void cut(int x,int y){spli(x,y);fa[x]=son[y][0]=0;upda(y);}
    
    il void link(int x,int y,int z)
    {
        if(find(x)==find(y))
        {
            spli(x,y);
            int aa=pos[y];//printf("%d
    ",aa);
            cut(e[aa-n].x,aa);cut(e[aa-n].y,aa);
            tim[aa-n]=z-n;
        }
        bert(x);fa[x]=z;
        bert(y);fa[y]=z;
    }
    
    void upd(int x)
    {
        t[x].v=t[t[x].l].v+t[t[x].r].v;
    }
    
    void build(int l,int r,int las,int &now,int v)
    {
        now=++cnt;t[now]=t[las];t[now].v++;
        if(l==r)return ;
        int mid=(l+r)>>1;
        if(v<=mid) build(l,mid,t[las].l,t[now].l,v);
        else build(mid+1,r,t[las].r,t[now].r,v);
    }
    
    int query(int l,int r,int x,int y,int v)
    {
        if(l==v) return t[y].v-t[x].v;
        int mid=(l+r)>>1;
        if(v<=mid) return query(l,mid,t[x].l,t[y].l,v)+t[t[y].r].v-t[t[x].r].v;
        else return query(mid+1,r,t[x].r,t[y].r,v);
    }
    
    int main()
    {
        n=read(),m=read();q=read(),tt=read();
        for(int i=0;i<=n;++i) val[i]=inf;
        for(int i=1;i<=m;++i)
        {
            e[i].x=read(),e[i].y=read();
            val[n+i]=i;tim[i]=m+1;
            if(e[i].x==e[i].y){tim[i]=i;continue;}
            link(e[i].x,e[i].y,n+i);
        }
        for(int i=1;i<=m;++i)
            build(0,m+1,rt[i-1],rt[i],tim[i]);
        for(int i=1,l,r;i<=q;++i)
        {
            l=read(),r=read();
            if(tt) l^=ans,r^=ans;
            printf("%d
    ",ans=n-query(0,m+1,rt[l-1],rt[r],r+1));
        }
        return 0;
    }
  • 相关阅读:
    对焦过程中消除摩尔纹
    Python3.x:Linux下安装python3.6
    Python3.x:Linux下退出python命令行
    Python3.x:ConfigParser模块的使用
    Python3.x:SQLAlchemy操作数据库
    Python3.x:遍历select下拉框获取value值
    Python3.x:Selenium中的webdriver进行页面元素定位
    Python3.x:selenium获取iframe内嵌页面的源码
    Python3.x:Selenium+PhantomJS爬取带Ajax、Js的网页
    Python3.x:将数据下载到xls时候用xml格式保存一份读取内容
  • 原文地址:https://www.cnblogs.com/rir1715/p/8253874.html
Copyright © 2011-2022 走看看