过了,但不是很懂
查看原帖
过了,但不是很懂
637073
wujingfey楼主2024/11/27 07:57

下面是我的代码,用的是线段树分治+可撤销并查集,在断边和建树过程中,我的右边界 rr 设置成 m+10m+10 就可以过,但设置成 mm 就只有 40pts40pts。为啥啊awa

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+7;
int n,m,cnt,tot,ans[N];
struct EDGE{
	int u,v,s,t;
}e[N];
struct Q{
	int t,x,y;
}q[N];
map<pair<int,int>,int> lst;
struct NODE{
	int l,r;
	vector<int> v;
	vector<int> q;
}tr[N<<2];
void build(int p,int l,int r){
	tr[p].l=l, tr[p].r=r;
	tr[p].v.clear();
	if(l==r) return;
	int mid=(l+r)>>1;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
}
void inse(int p,int l,int r,int i){
	if(l<=tr[p].l && tr[p].r<=r){
		tr[p].v.push_back(i);
		return;
	}
	int mid=(tr[p].l+tr[p].r)>>1;
	if(l<=mid) inse(p<<1,l,r,i);
	if(mid<r) inse(p<<1|1,l,r,i);
}
void insq(int p,int l,int i){//t=l插入询问i 
	if(tr[p].l == tr[p].r){
		tr[p].q.push_back(i);
		return;
	}
	int mid=(tr[p].l+tr[p].r)>>1;
	if(l<=mid) insq(p<<1,l,i);
	else insq(p<<1|1,l,i);
}
int fa[N],sz[N],high[N],tp;
struct ST{
	int x,y,f,num;
	//x->y, f=1表示深度+1了,num表示新增sz 
}st[N];
int find(int x){
	if(fa[x]==x) return x;
	return find(fa[x]);
}
void merge(int x,int y){
	x=find(x),y=find(y);
	if(high[x]>high[y]) swap(x,y);
	st[++tp]={x,y,(high[x]==high[y]),sz[x]};
	fa[x]=y, sz[y]=sz[x]+sz[y];
	if(high[x]==high[y]) high[y]++;
}
void solve(int p){
	int nw=tp;
	for(auto i:tr[p].v){//插入边 
		int u=e[i].u, v=e[i].v;
		merge(u,v);
	}
	if(tr[p].l==tr[p].r){//叶子结点回答询问 
		for(auto i:tr[p].q){
			int x=q[i].x, y=q[i].y;
			x=find(x), y=find(y);
			ans[q[i].t]=sz[x]*sz[y];
		}
	}
	if(tr[p].l!=tr[p].r){	
		solve(p<<1);
		solve(p<<1|1);
	}
	while(tp>nw){
		sz[st[tp].y]-=st[tp].num;
		high[st[tp].y]-=st[tp].f;
		fa[st[tp].x]=st[tp].x;
		tp--;
	}
}
signed main(){
//	freopen("P4219_2.in","r",stdin);
//	freopen("P4219.out","w",stdout);
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		fa[i]=i;
		sz[i]=1;
		high[i]=1;
	}
	for(int i=1;i<=m;i++){
		char op; int x,y;
		cin>>op>>x>>y;
		if(x>y) swap(x,y);
		if(op=='A'){
			e[++cnt]={x,y,i,m+10};
			lst[{x,y}]=cnt;
		}else{
			int p=lst[{x,y}];
			e[p].t=i-1;
			e[++cnt]={x,y,i+1,m+10};
			lst[{x,y}]=cnt;
			q[++tot]={i,x,y};//在i时刻有一个询问x,y 
		}
	}
	build(1,1,m+10);
	for(int i=1;i<=cnt;i++){
		inse(1,e[i].s,e[i].t,i);
	}
	for(int i=1;i<=tot;i++){
		insq(1,q[i].t,i);
	}
	for(int i=1;i<=m;i++) ans[i]=-1;
	solve(1);
	for(int i=1;i<=m;i++){
		if(ans[i]>=0) cout<<ans[i]<<'\n';
	}
	return 0;
}
/*
8 6
A 1 2
A 2 3
A 3 4
Q 2 3
A 2 5
Q 2 3

1_2 1_6
2_3 2_3
3_4 3_6
2_3 5_5
2_5 5_6
*/
2024/11/27 07:57
加载中...