UVALive 4730 Kingdom(线段树区间修改+并查集)
2015-08-10 14:32
435 查看
题意:
有T组测试数据,每组数据的N表示有N个城市,接下来的N行里每行给出每个城市的坐标(0<=x,y<=1000000)(0<=x,y<=1000000)。然后有M(1<M<200000)(1个操作,操作有两类:
(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万就可以过了。
mymy codecode
[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; }
相关文章推荐
- 前端学习
- 不用也要知道的几种算法(PHP版本)
- (转)android自定义控件
- 学渣如何打败学霸
- oracle查看awr、addm报告
- Java面向对象的三种特性
- fcntl的close-on-exec标志
- sitemesh
- Oracle_导入大批量数据到表中的方法
- 最小二乘回归
- iOS学习笔记:UISearchBar使用
- Python入门 Python变量和数据类型
- 如何收集 NGINX 指标(第二篇)
- JS正则表达式详解
- HTML中嵌入JavaScript脚本
- Dijkstra
- 获取select赋值
- 并查集 - UVALive 6889 City Park
- 技术改变命运
- 利用系统ContentProvider增加联系人