有T组测试数据,每组数据的N表示有N个城市,接下来的N行里每行给出每个城市的坐标 (0<=x,y<=1000000) 。
然后有M (1<M<200000) 个操作,操作有两类:
(1)”road A B”,表示将城市A和城市B通过一条道路连接,如果A和B原来属于不同的城市群,经过这个操作,A和B就在一个城市群里了,保证每条道路不会和其他道路相交(除了端点A和B)。
(2)”line C”,表示查询当穿过y=C的直线,有多少个城市群、这几个城市群一共有多少个城市。(注意:C是一个小数位为0.5的小数)
考录到联通块,所以可以想到用并查集,并查集的根节点保存每个城市群的的最大的y值和最小的y值,以及这个城市群内有多少个点。
每次合并两个集合的时候,先把原先城市群里的东西从线段树里去掉,更新好这个城市群之后,再放下去。
注意:y的范围比较大,又有小数,所以我把y坐标乘2,我把数组开到了200万,结果超时了,后来听了帆神学长的建议,考虑到C是一个小数位为0.5的小数,于是我把所有的左边界前移一位,询问C的时候把C+0.5,这样就避免了小数带来的麻烦,数组只要开到100万就可以过了。
my code
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ls (o<<1)
#define rs (o<<1|1)
#define lson ls, L, M
#define rson rs, M+1, R
using namespace std;
const int MAXY = (int)1e6 + 5;
const int MAXN = (int)1e5 + 5;
struct Node {
int state, city;
int adds, addc; //lazy
Node() { state = city = adds = addc = 0;}
} node[MAXY * 3];
int n, q;
void build(int o, int L, int R) {
node[o] = Node();
if(L == R) return ;
int M = (L + R)/2;
build(lson);
build(rson);
}
void pushDown(int o) {
if(node[o].addc) {
node[ls].addc += node[o].addc;
node[rs].addc += node[o].addc;
node[ls].city += node[o].addc;
node[rs].city += node[o].addc;
node[o].addc = 0;
}
if(node[o].adds) {
node[ls].adds += node[o].adds;
node[rs].adds += node[o].adds;
node[ls].state += node[o].adds;
node[rs].state += node[o].adds;
node[o].adds = 0;
}
}
Node query(int o, int L, int R, int pos) {
if(L == R) return node[o];
pushDown(o);
int M = (L + R)/2;
if(pos <= M) return query(lson, pos);
else return query(rson, pos);
}
void modify(int o, int L, int R, int ql, int qr, int val, char type) {
if(ql <= L && R <= qr) {
if(type == 'c') {
node[o].city += val;
node[o].addc += val;
}else {
node[o].state += val;
node[o].adds += val;
}
return ;
}
pushDown(o);
int M = (L + R)/2;
if(ql <= M) modify(lson, ql, qr, val, type);
if(qr > M) modify(rson, ql, qr, val, type);
}
int fa[MAXN];
int city[MAXN], state[MAXN], low[MAXN], high[MAXN];
void init() {
int x, y;
for(int i = 0; i < n; i++) {
scanf("%d%d", &x, &y);
fa[i] = i;
city[i] = state[i] = 1;
low[i] = high[i] = y;
}
}
int find(int u) {
return (fa[u] == u) ? fa[u] : fa[u] = find(fa[u]);
}
void Union(int u, int v) {
int a = find(u), b = find(v);
if(a == b) return ;
if(low[a] < high[a]) {
modify(1, 0, MAXY, low[a]+1, high[a], -city[a], 'c');
modify(1, 0, MAXY, low[a]+1, high[a], -1, 's');
}
if(low[b] < high[b]) {
modify(1, 0, MAXY, low[b]+1, high[b], -city[b], 'c');
modify(1, 0, MAXY, low[b]+1, high[b], -1, 's');
}
if(a > b) swap(a, b);
fa[b] = a;
low[a] = min(low[a], low[b]);
high[a] = max(high[a], high[b]);
city[a] += city[b];
state[a] = 1;
modify(1, 0, MAXY, low[a]+1, high[a], city[a], 'c');
modify(1, 0, MAXY, low[a]+1, high[a], state[a], 's');
}
char oper[10];
int main() {
int T;
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
init();
build(1, 0, MAXY);
scanf("%d", &q);
int u, v;
double pos;
while(q--) {
scanf("%s", oper);
if(oper[0] == 'r') {
scanf("%d%d", &u, &v);
Union(u, v);
}else {
scanf("%lf", &pos);
Node ret = query(1, 0, MAXY, (int)(pos + 1));
printf("%d %d\n", ret.state, ret.city);
}
}
}
return 0;
}