Kingdom LA4730

The meaning of the question is to simplify the plane with n points (n<=100000, coordinates <=1 million), two operations, one is to select two points to connect sides, the other is to ask how many connections are there on a certain y coordinate blocks, and how many points are connected by these connected blocks

The general idea is to merge the set + line segment tree, and maintain the line segment tree when the merged set is merged. Open two line segment trees, one to maintain the number of points on each connected block on each y coordinate, and one to maintain the number of connected blocks on each y coordinate

Note that the x-coordinate of each point in this question has no effect on the answer, so just record the height.

And check and maintain four quantities, father, the number of connected block points with this as the root, the maximum height of the connected block, and the minimum height of the connected block

In the code, f1 is set to the top of the maximum height, which is discussed in three cases



Originally thought that the data was 1 million universal cards in the past, and it was more than 100,000 after discretization, so I was too lazy to not discretize it. 

I didn't expect that it would be T without discretization, and there was another discretization in the middle. 

//I originally thought that the data was 1 million universal cards, and it was more than 100,000 after discretization, so I was too lazy to not discretize it.
//I didn't expect that it would be T without discretization, and there was another discretization in the middle.
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN (200010)
#define ls ((rt<<1)+1)
#define rs ((rt<<1)+2)
#define mid ((l+r)>>1)
#define fr(i,s,t) for (i=s;i<=t;i++)
#define Cl(a) memset(a,0,sizeof(a))
using namespace std;
int n,H[MAXN],Min[MAXN],Max[MAXN],m,fa[MAXN],sum[MAXN],Up,temp[MAXN];
char S[200];
int end(int x){
	if (fa[x]==x) return x;
	fa [x] = fin (fa [x]);
	return fa[x];
}
struct Order{
	int opt,x,y;
	void Read(){
		scanf("%s",S);
		if (S[0]=='r') opt=1;
		if (opt==1) scanf("%d %d",&x,&y);
		else{
			double d; scanf("%lf",&d); x=d; x++;
		}
	}
}O[MAXN];
struct Tree{
	int T[MAXN*5];
	void Clear(){
		memset(T,0,sizeof(T));
	}
	void update(int rt,int l,int r,int L,int R,int val){
		if (L>R) return;
		if (l>=L&&r<=R){
			T[rt]+=val;
			return;
		}
		if (L<=mid) update(ls,l,mid,L,R,val);
		if (R>mid) update(rs,mid+1,r,L,R,val);
	}
	int Query(int rt,int l,int r,int pos){
		int res=0;
		res+=T[rt];
		if (l==r) return res;
		if (pos<=mid) return res+Query(ls,l,mid,pos);
		else return res+Query(rs,mid+1,r,pos);
	}
}T[2];
void Merge(int x,int y){
	int f1=end(x),f2=end(y);
	if (f1==f2) return;
	if (Max[f1]<Max[f2]) swap(f1,f2),swap(x,y);
	//1
	if (Min[f1]>Max[f2]){
		T[1].update(0,1,Up,Min[f1],Max[f1]-1,-sum[f1]);
		T[1].update(0,1,Up,Min[f2],Max[f2]-1,-sum[f2]);
		fa[f2]=f1; sum[f1]+=sum[f2];
		T[1].update(0,1,Up,Min[f2],Max[f1]-1,sum[f1]);
		T[0].update(0,1,Up,Max[f2],Min[f1]-1,1);
		Min[f1]=Min[f2];
		return;	
	}
	//2
	if (Min[f2]>=Min[f1]){
		T[0].update(0,1,Up,Min[f2],Max[f2]-1,-1);
		T[1].update(0,1,Up,Max[f2],Max[f1]-1,sum[f2]);
		T[1].update(0,1,Up,Min[f1],Min[f2]-1,sum[f2]);
		fa[f2]=f1; sum[f1]+=sum[f2];
		return;
	}
	//3
	T[0].update(0,1,Up,Min[f1],Max[f2]-1,-1);
	T[1].update(0,1,Up,Max[f2],Max[f1]-1,sum[f2]);
	T[1].update(0,1,Up,Min[f2],Min[f1]-1,sum[f1]);
	fa[f2]=f1; sum[f1]+=sum[f2];
	Min[f1]=Min[f2];
}
void lsh(){
	memset(temp,0,sizeof(temp));
	int i,k=0;
	for (i=1;i<=n;i++) temp[++k]=H[i];
	for (i=1;i<=m;i++) if (O[i].opt!=1) temp[++k]=O[i].x;
	sort(temp+1,temp+k+1);
	Up=unique(temp+1,temp+k+1)-temp-1;
	fr(i,1,n) H[i]=lower_bound(temp+1,temp+Up+1,H[i])-temp;
	fr(i,1,m) if (O[i].opt!=1) O[i].x=lower_bound(temp+1,temp+Up+1,O[i].x)-temp;
}
void Work(){
	Cl(H); Cl(fa); Cl(Min); Cl(Max); Cl(sum);
	Cl(O); Cl(T);
	Up=0;
	scanf("%d",&n);
	int i,x,y;
	fr(i,1,n) scanf("%d %d",&x,&H[i]),H[i]++;
	scanf("%d",&m);
	fr(i,1,m) O[i].Read();
	lsh();
	fr(i,1,n) fa[i]=i,Min[i]=Max[i]=H[i],sum[i]=1;
	
	for (i=1;i<=m;i++){
		int opt=O[i].opt;
		if (opt==1) x=O[i].x,y=O[i].y,Merge(x+1,y+1);
		else{
			x=O[i].x;
			printf("%d %d\n",T[0].Query(0,1,Up,x),T[1].Query(0,1,Up,x));
		}
	}
}
int main(){
	int T_Num; cin>>T_Num;
	while (T_Num--) Work();
}



Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325935907&siteId=291194637