[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!

原文地址:https://www.cnblogs.com/PaperCloud/p/11178074.html