LG-P5607

题解区不让交了,遂来博客园写一发。

感觉和题解区的两种暴力方法一起使用差不多,写了根号分治+在线的做法,理论时间复杂度达到了 \(O(10^9)\),但常数小一点(甚至比那些时间复杂度完全正确的跑的快,拿到了最优解)。

两种暴力方法:

1.每次询问直接比较,暴力求出其并集大小,并算出交集。

2.维护 \(S_{i,j}\) 表示集合 \(i\) 和集合 \(j\) 的交集大小,并用 Bitset 维护一个集合里有哪些数,添加时进行实时维护。

易发现第一种暴力方法适合较小的集合,第二种方法适合数量少的集合。

那么根号分治,大小小于 \(B\) 的集合用第一种,大小大于 \(B\) 的集合用第二种,一旦过程中发现某个集合通过添加大于 \(B\), 则为其添加一个 Bitset 并计算与其余大集合的答案,加入\(S\)。

(\(B\) 的值进行了略微调整,在实际数据中能跑得更快。)

CODE
#include<bits/stdc++.h>
#define fst first
#define sec second
#define mkp(a,b) make_pair(a,b)
#define usetime() (double)clock () / CLOCKS_PER_SEC * 1000.0
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
const int maxn=1e6+5,B=400;
char *p1,*p2,buf[100000];
#define nc() (p1==p2 && (p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int read(){
	int x=0,f=1;
	char ch=nc();
	while(ch<48||ch>57)
	{
		if(ch=='-')
			f=-1;
		ch=nc();
	}
	while(ch>=48&&ch<=57)
		x=x*10+ch-48,ch=nc();
	return x*f;
}
void write(int x){
	if(x<0)
		putchar('-'),x=-x;
	if(x>9)
		write(x/10);
	putchar(x%10+'0');
	return;
}
bitset<maxn> bt[2505];
int s[2505][2505];
int tg[maxn],rg[2505],tot=0;
vector<int> v[maxn];
bool t[maxn];
int sz[maxn];
int main(){
	int m; m=read();
	while(m--){
		int op,a,b;
		op=read(),a=read(),b=read();
		if(op==1){
			v[a].push_back(b),++sz[a];
			if(sz[a]==B){
				++tot,tg[a]=tot,rg[tot]=a;
				for(auto i : v[a]){
					bt[tot][i]=1;
				}
				for(int i=1;i<tot;i++){
					s[i][tot]=sz[rg[i]]+sz[a];
					for(auto j : v[a]){
						s[i][tot]-=bt[i][j];
					}
				}
			}
			else if(sz[a]>B){
				bt[tg[a]][b]=1;
				int tga=tg[a];
				for(int i=1;i<tg[a];i++){
					s[i][tga]+=(!bt[i][b]);
				}
				for(int i=tg[a]+1;i<=tot;i++){
					s[tga][i]+=(!bt[i][b]);
				}
			}
		}
		else{
			if(sz[a]<sz[b]) swap(a,b);
			int ans=sz[a]+sz[b];
			int tga=tg[a];
			if(sz[a]<B){
				for(auto i : v[b]) t[i]=1;
				for(auto i : v[a]) ans-=t[i];
				for(auto i : v[b]) t[i]=0;
			}
			else if(sz[b]<B){
				for(auto i : v[b]) ans-=bt[tga][i];
			}
			else{
				if(tg[a]>tg[b]) swap(a,b);
				ans=s[tg[a]][tg[b]];
				if(tg[a]==tg[b]) ans=sz[a];
			}
			write(ans); putchar('\n');
		}
	}
	return 0;
}
//^o^
posted @ 2026-06-28 16:58  huangems  阅读(48)  评论(1)    收藏  举报