[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\n",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!
致虚极,守静笃,万物并作,吾以观其复