码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 3514 Codechef MARCH14 GERALD07加强版

时间:2019-02-22 12:29:23      阅读:166      评论:0      收藏:0      [点我收藏+]

标签:www.   nod   实现   com   get   http   res   open   处理   

bzoj 3514 Codechef MARCH14 GERALD07加强版

  • 所谓的加强版就是比原题多了个强制在线.原题显然可以莫队随便乱搞一下,就过了.
  • 本题强制在线,我们只能通过预处理的手段,高效回答每次询问.
  • 考虑从前往后依次加入边.如果加入的边是树边,即加入它后图中没有环,那么它会使整张图联通块个数 \(-1\),否则联通块个数不变.
  • 若加入边 \(i\) 会成环,我们在环上删掉标号最小的那条边,记这个标号为 \(f\) ,那么当询问区间的 \(l\) 大于 \(f\) 时,边 \(i\) 就是树边,贡献为 \(-1\) ,否则贡献为 \(0\) .
  • \(LCT\) 来实现删边加边操作,每次查询只需要知道 \([l,r]\) 这个区间内有多少 \(f\) 是小于 \(l\) 的.用主席树实现即可.
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
#define pii pair<int,int>
inline int read()
{
    int x=0;
    bool pos=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar())
        if(ch=='-')
            pos=0;
    for(;isdigit(ch);ch=getchar())
        x=x*10+ch-'0';
    return pos?x:-x;
}
const int inf=1e9;
const int MAXN=4e5+10;
int n,m,Q,type;
namespace LCT{
    int stk[MAXN],tp;
    struct node{
        int ch[2],fa;
        int val,mn;
        int rev;
        node()
            {
                ch[0]=ch[1]=fa=0;
                val=mn=inf;
                rev=0;
            }
    }tree[MAXN];
    void init(int id)
        {
            tree[id+m].val=tree[id+m].mn=id;
        }
    #define root tree[x]
    #define lson tree[root.ch[0]]
    #define rson tree[root.ch[1]]
    void pushup(int x)
        {
            root.mn=min(root.val,min(lson.mn,rson.mn));
        }
    void inverse(int x)
        {
            swap(root.ch[0],root.ch[1]);
            root.rev^=1;
        }
    void pushdown(int x)
        {
            if(root.rev)
                {
                    if(root.ch[0])
                        inverse(root.ch[0]);
                    if(root.ch[1])
                        inverse(root.ch[1]);
                    root.rev=0;
                }
        }
    bool isroot(int x)
        {
            int y=root.fa;
            return tree[y].ch[0]!=x && tree[y].ch[1]!=x;
        }
    void rotate(int x)
        {
            int y=tree[x].fa,z=tree[y].fa;
            int k=tree[y].ch[1]==x;
            
            if(!isroot(y))
                tree[z].ch[tree[z].ch[1]==y]=x;
            tree[x].fa=z;
            
            tree[y].ch[k]=tree[x].ch[k^1];
            tree[tree[x].ch[k^1]].fa=y;
            
            tree[x].ch[k^1]=y;
            tree[y].fa=x;
            pushup(y);
        }
    void splay(int x)
        {
            tp=0;
            stk[++tp]=x;
            for(int pos=x;!isroot(pos);pos=tree[pos].fa)
                stk[++tp]=tree[pos].fa;
            while(tp)
                pushdown(stk[tp--]);
            while(!isroot(x))
                {
                    int y=tree[x].fa,z=tree[y].fa;
                    if(!isroot(y))
                        (tree[y].ch[0]==x)^(tree[z].ch[0]==y)?rotate(x):rotate(y);
                    rotate(x);
                }
            pushup(x);
        }
    void Access(int x)
        {
            for(int y=0;x;y=x,x=tree[x].fa)
                {
                    splay(x);
                    tree[x].ch[1]=y;
                    pushup(x);
                }
        }
    void makeroot(int x)
        {
            Access(x);
            splay(x);
            inverse(x);
        }
    int findroot(int x)
        {
            Access(x);
            splay(x);
            while(tree[x].ch[0])
                x=tree[x].ch[0];
            return x;
        }
    void split(int x,int y)
        {
            makeroot(x);
            Access(y);
            splay(y);
        }
    void Link(int x,int y)
        {
            makeroot(x);
            tree[x].fa=y;
        }
    void Cut(int x,int y)
        {
            split(x,y);
            tree[y].ch[0]=0;
            tree[x].fa=0;
            pushup(y);
        }
}
namespace SEG{
    struct node{
        int l,r;
        int sum,ls,rs;
    }Tree[MAXN*30];
    #define Root Tree[o]
    #define Lson Tree[root.ls]
    #define Rson Tree[root.rs]
    int rt[MAXN],idx;
    void BuildTree(int &o,int l,int r)
        {
            o=++idx;
            Root.sum=0,Root.ls=0,Root.rs=0;
            Root.l=l,Root.r=r;
            if(l==r)
                return;
            int mid=(l+r)>>1;
            BuildTree(Root.ls,l,mid);
            BuildTree(Root.rs,mid+1,r);
        }
    void update(int &o,int pre,int pos)
        {
            o=++idx;
            Root=Tree[pre];
            ++Root.sum;
            int l=Root.l,r=Root.r;
            if(l==r)
                return;
            int mid=(l+r)>>1;
            if(pos<=mid)
                update(Root.ls,Tree[pre].ls,pos);
            else
                update(Root.rs,Tree[pre].rs,pos);
        }
    int query(int o,int L,int R)
        {
            if(L>R) 
                return 0;
            int l=Root.l,r=Root.r;
            if(r<L || R<l)
                return 0;
            if(L<=l && r<=R)    
                return Root.sum;
            int mid=(l+r)>>1;
            int res=0;
            if(L<=mid)
                res+=query(Root.ls,L,R);
            if(R>mid)
                res+=query(Root.rs,L,R);
            return res;
        }
}
int lastans=0;
int eu[MAXN],ev[MAXN];
int main()
{
//  freopen("7.in","r",stdin);
//  freopen("ans.out","w",stdout);
    SEG::idx=0;
    n=read(),m=read(),Q=read(),type=read();
    SEG::BuildTree(SEG::rt[0],0,m);
    for(int i=1;i<=m;++i)
        {
        //  cerr<<"solving "<<i<<endl;
            if(i==9434)
                {
                    int debug=1;
                }
            int u=read(),v=read();
            if(u==v)
                {
                    SEG::update(SEG::rt[i],SEG::rt[i-1],i);
                //  printf("total:%d\n",SEG::query(SEG::rt[i],0,m-1));
                    continue;
                }
            eu[i]=u,ev[i]=v;
            int ufa=LCT::findroot(u);
            int vfa=LCT::findroot(v);
            if(ufa==vfa)
                {
                    LCT::split(u,v);
                    int id=LCT::tree[LCT::tree[v].ch[0]].mn;
                    LCT::Cut(id+m,eu[id]);
                    LCT::Cut(id+m,ev[id]);
                    LCT::Link(i+m,u);
                    LCT::Link(i+m,v);
                    SEG::update(SEG::rt[i],SEG::rt[i-1],id);
                }
            else
                {
                    LCT::init(i);
                    LCT::Link(i+m,u);
                    LCT::Link(i+m,v);
                    SEG::update(SEG::rt[i],SEG::rt[i-1],0);
                }
        //  printf("total:%d\n",SEG::query(SEG::rt[i],0,m-1));
        }
    while(Q--)
        {
            int L=read(),R=read();
            if(type)
                L^=lastans,R^=lastans;
            int Rans=SEG::query(SEG::rt[R],0,L-1);
            int Lans=SEG::query(SEG::rt[L-1],0,L-1);
            lastans=n-(Rans-Lans);
            printf("%d\n",lastans);
        }
    return 0;
}

bzoj 3514 Codechef MARCH14 GERALD07加强版

标签:www.   nod   实现   com   get   http   res   open   处理   

原文地址:https://www.cnblogs.com/jklover/p/10417237.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!