zoukankan      html  css  js  c++  java
  • [bjoi2014]大融合

    传送门

    Description

    加边以及询问点的联通块大小

    Solution 

    线段树分治

    一直都没怎么打过


    Code 

    /*
        2019/7/12 by pac 
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        return x*f;
    }
    #define reg register
    const int MN=2e5+5;
    int N,Q;
    class DSU
    {
        int siz[MN],fa[MN],st_l[MN],st_r[MN];
        int tp;
        public:
        void init()
        {
            register int i;
            for(i=1;i<=N;++i) fa[i]=i,siz[i]=1;
            tp=0;
        }
        int getf(int x){return fa[x]==x?x:getf(fa[x]);}
        void union_(int x,int y)
        {
            x=getf(x);
            y=getf(y);
            if(x==y) return;
            if(siz[x]>siz[y]) swap(x,y);
            st_l[++tp]=x;st_r[tp]=y;
            fa[x]=y;siz[y]+=siz[x];
        }
        void getback(int t)
        {
            reg int l,r;
            for(;tp>t;--tp)
            {
               l=st_l[tp],r=st_r[tp];
               siz[r]-=siz[l];fa[l]=l;
            }
        }
        int Ans(int x,int y){return siz[getf(x)]*siz[getf(y)];}
        int Tp(){return tp;}
    }dsu;
    struct edge{
        int a,b,s;
        edge() {}
        edge(int a,int b,int s):a(a),b(b),s(s) {}
        bool operator <(const edge &o)const {return a<o.a||(a==o.a&&b<o.b);}
        bool operator ==(const edge &o) const {return a==o.a&&b==o.b;}
    };
    
    std::vector<pair<int,int> > T_ed[MN<<2];
    
    int L,R;
    
    set<edge> S;
    set<edge>::iterator it;
    vector<pair<int,int> > id[MN];
    
    void Md(int k,int l,int r,int x,int y,int a,int b)
    {
        if(l==a&&r==b){T_ed[k].push_back(make_pair(x,y));return;}
        int mid=(l+r)>>1;
        if(b<=mid) Md(k<<1,l,mid,x,y,a,b);
        else if(a>mid) Md(k<<1|1,mid+1,r,x,y,a,b);
        else Md(k<<1,l,mid,x,y,a,mid),Md(k<<1|1,mid+1,r,x,y,mid+1,b);
    }
    
    void walk_tree(int x,int l,int r)
    {
        reg int pre=dsu.Tp(),i;
        for(i=T_ed[x].size()-1;~i;--i){dsu.union_(T_ed[x][i].first,T_ed[x][i].second);}
        if(l==r&&id[l].size()) printf("%d
    ",dsu.Ans(id[l][0].first,id[l][0].second));
        if(l!=r)
        {
            reg int mid=(l+r)>>1;
            walk_tree(x<<1,l,mid);walk_tree(x<<1|1,mid+1,r);
        }
        dsu.getback(pre);
    }
    
    int main()
    {
        N=read();Q=read();L=1;R=Q+1<<1;
        register int i,x,y,tim;
        char sh[10];
        S.clear();
        for(i=1,tim=1;i<=Q;++i)
        {
            scanf("%s%d%d",sh,&x,&y);
            if(sh[0]=='A') S.insert(edge(x,y,tim));
            else
            {
                it=S.find(edge(x,y,0));
                if(it==S.end()){
    				std::swap(x,y),it=S.find(edge(x,y,0));
                }
    				
                Md(1,L,R,x,y,it->s,tim);
    			S.erase(it);
                ++tim;
                id[tim].push_back(make_pair(x,y));
                ++tim;
                S.insert(edge(x,y,tim));
            }
        }
        for(it=S.begin();it!=S.end();++it) Md(1,L,R,it->a,it->b,it->s,tim);
        dsu.init();
        walk_tree(1,L,R);
        return 0;
    }
    


    Blog来自PaperCloud,未经允许,请勿转载,TKS!

  • 相关阅读:
    如何不传入对象就获得某对象的方法---ThreadLocal类
    Linux系统主目录被更改,怎么修改回去?
    tree命令的安装
    Linux命令学习man
    当重载函数的参数是Object和Object数组的时候会发生什么情况!!!
    Linux学习(二)之内核、系统调用、库
    使用puttygen转换OpenSSH SSH2私钥为RSA PEM格式
    docker-compose使用详解
    svn迁移到gitlab
    linux快速启动http端口
  • 原文地址:https://www.cnblogs.com/PaperCloud/p/11178074.html
Copyright © 2011-2022 走看看