题意:有n个城市,给出这n个城市的坐标,初始没有道路连通,有q个指令,
road A B:在城市A和城市B之间连接一条双向道路,保证这条道路不和其他道路在非端点处相交。
line C:询问y = C的水平线和多少个州相交,以及这些州一共包含多少座城市,C小数部分保证为0.5
思路:记录每个洲的纵坐标最小值最大值, 当连接A, B时, 如果A, B处于同一连通块,那么不做处理, 否则, 在A所在连通块的纵坐标范围内州数减去1,城市数减去所在连通块的城市数,B也是如此, 然后连接起来之后的连通块纵坐标范围内加上原来减去的和, 州数加1, lazy标记一下即可。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<iostream>
#include<algorithm>
const int maxn = 1e5 + 10;
const int INF = 1e9;
using namespace std;
struct msg {
int city, sta;
} C[maxn * 20];
int n, x, T, q, A, B;
int ymax[maxn], ymin[maxn];
int d[maxn * 4], y[maxn];
int sum[maxn];
int pa[maxn], int_line;
char op[10];
void init() {
for(int i = 0; i < maxn; i++) {
sum[i] = 1; pa[i] = i;
}
for(int i = 0; i < 20 * maxn; i++) {
C[i].city = 0;
C[i].sta = 0;
}
}
int findset(int x) { return x == pa[x] ? x : pa[x] = findset(pa[x]); }
int ql, qr, city, sta;
void pushdown(int o) {
int o1 = o << 1, o2 = o << 1 | 1;
C[o1].city += C[o].city;
C[o2].city += C[o].city;
C[o].city = 0;
C[o1].sta += C[o].sta;
C[o2].sta += C[o].sta;
C[o].sta = 0;
}
void update(int o, int l, int r) {
if(l > qr || r < ql) return ;
if(l >= ql && r <= qr) {
C[o].city += city;
C[o].sta += sta;
return ;
}
pushdown(o);
int mid = (l + r) >> 1;
int o1 = o << 1, o2 = o << 1 | 1;
if(ql <= mid) update(o1, l, mid);
if(qr > mid) update(o2, mid + 1, r);
}
msg query(int o, int l, int r) {
if(l == r) return C[o];
int mid = (l + r) >> 1;
int o1 = o << 1, o2 = o << 1 | 1;
pushdown(o);
if(x <= mid) return query(o1, l, mid);
else return query(o2, mid + 1, r);
}
void unit(int a, int b, int R) {
int na = findset(a);
int nb = findset(b);
if(na == nb) return ;
int nax = ymin[na], nay = ymax[na];
int nbx = ymin[nb], nby = ymax[nb];
sta = -1; city = -sum[na];
ql = lower_bound(d, d + R, nax) - d;
qr = lower_bound(d, d + R, nay) - d;
update(1, 0, R);
sta = -1; city = -sum[nb];
ql = lower_bound(d, d + R, nbx) - d;
qr = lower_bound(d, d + R, nby) - d;
update(1, 0, R);
pa[na] = nb; sum[nb] += sum[na];
ymin[nb] = min(ymin[na], ymin[nb]);
ymax[nb] = max(ymax[na], ymax[nb]);
sta = 1; city = sum[nb];
ql = lower_bound(d, d + R, ymin[nb]) - d;
qr = lower_bound(d, d + R, ymax[nb]) - d;
update(1, 0, R);
}
int main() {
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
init();
int nn = 0;
for(int i = 0; i < n; i++) {
scanf("%d %d", &x, &y[i]);
y[i] *= 2;
ymax[i] = ymin[i] = y[i];
d[nn++] = y[i];
d[nn++] = y[i] + 1;
d[nn++] = y[i] - 1;
}
sort(d, d + nn);
nn = unique(d, d + nn) - d;
for(int i = 0; i < n; i++) {
x = lower_bound(d, d + nn, y[i]) - d;
ql = qr = x;
city = sta = 1;
update(1, 0, nn);
}
scanf("%d", &q);
while(q--) {
scanf("%s", op);
if(op[0] == 'r') {
scanf("%d %d", &A, &B);
unit(A, B, nn);
} else {
double c;
scanf("%lf", &c);
int_line = (int)(c * 2);
x = lower_bound(d, d + nn, int_line) - d;
msg ans = query(1, 0, nn);
printf("%d %d\n", ans.sta, ans.city);
}
}
}
return 0;
}