• bzoj3514


    题解:

    每一次加入一条边,记录一下弹出了那一条边

    然后用lct维护即可

    计算出来后,再用主席树做l-r的值

    代码:

    #include<bits/stdc++.h>
    typedef long long ll;
    const int N=400005;
    using namespace std;
    int type,n,m,Q,lastans,top,l,r,tot,sz,s[N],st[N],root[N];
    int c[N][2],fa[N],val[N],mn[N],sum[N*10],ls[N*10],rs[N*10],rev[N];
    struct edge{int u,v;}e[N];
    int isroot(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;}
    void update(int x)
    {
        int l=c[x][0],r=c[x][1];
        mn[x]=x;
        if (val[mn[l]]<val[mn[x]])mn[x]=mn[l];
        if (val[mn[r]]<val[mn[x]])mn[x]=mn[r];    
    }
    void pushdown(int x)
    {
        int l=c[x][0],r=c[x][1];
        if (rev[x])
         {
            rev[x]^=1;rev[l]^=1;rev[r]^=1;
            swap(c[x][0],c[x][1]);
         }
    }
    void rotate(int x)
    {
        int y=fa[x],z=fa[y],l,r;
        if (c[y][0]==x)l=0;else l=1;r=l^1;
        if (!isroot(y))
          {
            if(c[z][0]==y)c[z][0]=x;
            else c[z][1]=x;
         }
        fa[y]=x;fa[x]=z;fa[c[x][r]]=y;
        c[y][l]=c[x][r];c[x][r]=y;
        update(y);update(x);
    }
    void down(int x){if (!isroot(x))down(fa[x]);pushdown(x);}
    void splay(int x)
    {
        down(x);
        for (int y=fa[x];!isroot(x);rotate(x),y=fa[x])
         if (!isroot(y))rotate((c[y][0]==x)==(c[fa[y]][0]==y)?y:x);
    }
    void access(int x){for (int t=0;x;t=x,x=fa[x])splay(x),c[x][1]=t,update(x);}
    void makeroot(int x){access(x);splay(x);rev[x]^=1;}
    void link(int x,int y){makeroot(x);fa[x]=y;}
    void cut(int x,int y){makeroot(x);access(y);splay(y);c[y][0]=fa[x]=0;}
    int find(int x){access(x);splay(x);while (c[x][0])x=c[x][0];return x;}
    int query(int x,int y){makeroot(x);access(y);splay(y);return mn[y];}
    void insert(int l,int r,int x,int &y,int val)
    {
        y=++sz;
        sum[y]=sum[x]+1;
        if(l==r)return;
        ls[y]=ls[x];rs[y]=rs[x];
        int mid=(l+r)/2;
        if (val<=mid)insert(l,mid,ls[x],ls[y],val);
        else insert(mid+1,r,rs[x],rs[y],val);
    }
    int query(int l,int r,int x,int y,int val)
    {
        if (r==val)return sum[y]-sum[x];
        int mid=(l+r)/2;
        if (val<=mid)return query(l,mid,ls[x],ls[y],val);
        return sum[ls[y]]-sum[ls[x]]+query(mid+1,r,rs[x],rs[y],val);
    }
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&Q,&type);
        val[0]=1e9;
        for (int i=1;i<=n;i++)mn[i]=i,val[i]=1e9;
        for (int i=1;i<=m;i++)scanf("%d%d",&e[i].u,&e[i].v);
        tot=n;
        for (int i=1;i<=m;i++)
         {
            int u=e[i].u,v=e[i].v;
            if (u==v){st[i]=i;continue;}
            if (find(u)==find(v))
             {
                int t=query(u,v),x=val[t];
                st[i]=x;
                cut(e[x].u,t);cut(e[x].v,t);
             }
            tot++;
            mn[tot]=tot;val[tot]=i;
            link(u,tot);link(v,tot);
         }
        for (int i=1;i<=m;i++)insert(0,m,root[i-1],root[i],st[i]);
        while (Q--)
         {
             scanf("%d%d",&l,&r); 
            if (type)l^=lastans,r^=lastans;
            lastans=n-query(0,m,root[l-1],root[r],l-1);
            printf("%d
    ",lastans);
         }
        return 0;
    }
  • 相关阅读:
    关于天气插件代码
    新的起点了
    如何实现按下回车键实现搜索

    random模块
    循环导入问题
    模块的搜索路径
    import 和from…import
    模块四种形式
    面向过程编程
  • 原文地址:https://www.cnblogs.com/xuanyiming/p/8029552.html
Copyright © 2020-2023  润新知