以y轴建线段树 把坐标*2 初始化各节点 洲,城市 数目为0
并查集维护每一个连通块的 y坐标最大值最小值(x坐标没用)城市数目
合并时 如果是一个洲(城市数大于1) 线段树对应区间减掉该洲城市数
然后将两个洲合并,再在线段树对应区间增加大洲的城市数
(区间城市数不等于子区间城市数之和)
#include <bits/stdc++.h>
using namespace std;
const int Maxn=2e6+80;
int f[Maxn];
struct node
{
int l,r,city,zhou,addc,addz;
int mid()
{
return (l+r)/2;
}
} tree[Maxn<<2];
struct point
{
int maxn,minv,city,zhou;
};
point p[Maxn];
int findset(int u)
{
return u==f[u]?u:f[u]=findset(f[u]);
}
void build(int node,int l,int r)
{
tree[node].l=l,tree[node].r=r;
tree[node].city=tree[node].zhou=tree[node].addc=tree[node].addz=0;
if(l==r) return;
build(node<<1,l,(r+l)>>1);
build(node<<1|1,(r+l)/2+1,r);
}
void pushdown(int node)
{
if(tree[node].addc)
{
tree[node<<1].city+=tree[node].addc;
tree[node<<1|1].city+=tree[node].addc;
tree[node<<1].addc+=tree[node].addc;
tree[node<<1|1].addc+=tree[node].addc;
tree[node].addc=0;
}
if(tree[node].addz)
{
tree[node<<1].zhou+=tree[node].addz;
tree[node<<1|1].zhou+=tree[node].addz;
tree[node<<1].addz+=tree[node].addz;
tree[node<<1|1].addz+=tree[node].addz;
tree[node].addz=0;
}
}
void update(int node,int l,int r,int city,int zhou)
{
if(tree[node].l==l&&r==tree[node].r)
{
tree[node].city+=city;
tree[node].zhou+=zhou;
tree[node].addc+=city;
tree[node].addz+=zhou;
return ;
}
pushdown(node);
int mid=tree[node].mid();
if(mid<l)
{
update(node<<1|1,l,r,city,zhou);
}
else if(mid>=r)
{
update(node<<1,l,r,city,zhou);
}
else
{
update(node<<1,l,mid,city,zhou);
update(node<<1|1,mid+1,r,city,zhou);
}
}
int query(int node,int l,int r)
{
if(tree[node].l==l&&r==tree[node].r)
{
return node;
}
int mid=tree[node].mid();
pushdown(node);
if(mid<l)
{
query(node<<1|1,l,r);
}
else if(mid>=r)
{
query(node<<1,l,r);
}
else
{
query(node<<1,l,mid);
query(node<<1|1,mid+1,r);
}
}
void un(int x,int y)
{
int _x=findset(x),_y=findset(y);
if(f[_x]==f[_y])
{
return ;
}
f[_x]=_y;
if(p[_x].city>1)
update(1,p[_x].minv,p[_x].maxn,-p[_x].city,-1);
if(p[_y].city>1)
update(1,p[_y].minv,p[_y].maxn,-p[_y].city,-1);
p[_y].maxn=max(p[_x].maxn,p[_y].maxn);
p[_y].minv=min(p[_y].minv,p[_x].minv);
p[_y].city+=p[_x].city;
update(1,p[_y].minv,p[_y].maxn,p[_y].city,1);
}
int t,n,m;
int yy[Maxn];
int main()
{
scanf("%d",&t);
while(t--)
{
int x,y,Max=0;
scanf("%d",&n);
for(int i =1; i<=n; ++i) f[i]=i;
for(int i = 1; i <= n; ++i)
{
scanf("%d%d",&x,&y);
yy[i]=y*2;
Max=max(Max,yy[i]);
p[i].minv=p[i].maxn=y*2;
p[i].city=1;
p[i].zhou=1;
}
build(1,0,Max);
for(int i = 1; i<= n; ++i)
update(1,yy[i],yy[i],1,1);
scanf("%d",&m);
char ch[10];
double pos;
for(int i = 0; i < m; ++i)
{
scanf("%s",ch);
if(ch[0]=='r')
{
scanf("%d%d",&x,&y);
un(x+1,y+1);
}
else
{
scanf("%lf",&pos);
if(pos*2>Max) printf("0 0\n");
else
{
int no=query(1,pos*2,pos*2);
printf("%d %d\n",tree[no].zhou,tree[no].city);
}
}
}
}
return 0;
}