UVA1455 - Kingdom(并查集 + 线段树)

题目链接

题目大意:一个平面内,给你n个整数点,两种类型的操作:road x y 把city x 和city y连接起来,line fnum (浮点数小数点一定是0.5) 查询y = fnum这条直线穿过了多少个州和city。州指的是连通的城市。

解题思路:用并查集记录城市之间是否连通,还有每一个州的y的上下界。建立坐标y的线段树,然后每次运行road操作的时候,对范围内的y坐标进行更新;更新须要分三种情况:两个州是相离,还是相交,还是包括(这里指的是y坐标的关系);而且由于这里查询是浮点数,所以更新的时候[l,r]的时候,仅仅更新[l,r),这里的r留给它以下的点,这样每次查询的时候就能够查询(int)fnum。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm> using namespace std; const int maxn = 1e6 + 5;
const int N = 1e5 + 5;
#define lson(x) (x<<1)
#define rson(x) ((x<<1) | 1) struct Node { int l, r, ns, nc;
void set (int l, int r, int ns, int nc) { this->l = l;
this->r = r;
this->ns = ns;
this->nc = nc;
}
}node[4 * maxn]; void pushup (int u) { node[u].set (node[lson(u)].l, node[rson(u)].r, 0, 0);
} void add_node (int u, int adds, int addc) { node[u].ns += adds;
node[u].nc += addc;
} void pushdown (int u) { if (node[u].ns || node[u].nc) {
add_node(lson(u), node[u].ns, node[u].nc);
add_node(rson(u), node[u].ns, node[u].nc);
}
} void build (int u, int l, int r) { if (l == r) {
node[u].set (l, r, 0, 0);
return;
} int m = (l + r)>>1;
build (lson(u), l, m);
build (rson(u), m + 1, r);
pushup(u);
} void update (int u, int l, int r, int addc, int adds) { if (node[u].l >= l && node[u].r <= r) {
add_node (u, adds, addc);
return;
} int m = (node[u].l + node[u].r)>>1;
pushdown(u);
if (l <= m)
update (lson(u), l, r, addc, adds);
if (r > m)
update (rson(u), l, r, addc, adds);
pushup(u);
} int query (int u, int x) { if (node[u].l == x && node[u].r == x)
return u; int m = (node[u].l + node[u].r)>>1;
int ans; pushdown(u);
if (x <= m)
ans = query (lson(u), x);
else
ans = query (rson(u), x);
pushup(u);
return ans;
} int p[N], cnt[N], L[N], R[N];
int n, m; int getParent (int x) {
return x == p[x] ? x: p[x] = getParent (p[x]);
} void change (int u, int l, int r, int addc, int adds) { if (r < l) //注意
return;
update (u, l, r, addc, adds);
} void Union(int x, int y) { x = getParent (x);
y = getParent (y); if (x == y)
return; if (L[x] >= L[y])
swap(x, y); if (R[x] <= L[y]) {//相离 change (1, L[x], R[x] - 1, cnt[y], 0);
change (1, L[y], R[y] - 1, cnt[x], 0);
change (1, R[x], L[y] - 1, cnt[x] + cnt[y], 1);
} else if (R[y] <= R[x]) {//包括 change (1, L[x], L[y] - 1, cnt[y], 0);
change (1, R[y], R[x] - 1, cnt[y], 0);
change (1, L[y], R[y] - 1, 0, -1);
} else {//相交 change (1, L[x], L[y] - 1, cnt[y], 0);
change (1, R[x], R[y] - 1, cnt[x], 0);
change (1, L[y], R[x] - 1, 0, -1);
} p[x] = y;
cnt[y] += cnt[x];
L[y] = min (L[y], L[x]);
R[y] = max (R[y], R[x]);
} void init () { int x, y;
scanf ("%d", &n); for (int i = 0; i < n; i++) {
scanf ("%d%d", &x, &y);
p[i] = i;
cnt[i] = 1;
L[i] = R[i] = y; } scanf ("%d", &m);
build (1, 0, maxn - 5);
} void solve () { char str[100];
int x, y;
double q; for (int i = 0; i < m; i++) { scanf ("%s", str); if (str[0] == 'r') {
scanf ("%d%d", &x, &y);
Union(x, y);
} else {
scanf ("%lf", &q);
x = query (1, (int)q);
printf ("%d %d\n", node[x].ns, node[x].nc);
}
}
} int main () { int T;
scanf ("%d", &T); while (T--) { init();
solve();
}
return 0;
}

UVA1455 - Kingdom(并查集 + 线段树)的更多相关文章

  1. 并查集&线段树&树状数组&排序二叉树

    超级无敌巨牛逼并查集(带权并查集)https://vjudge.net/problem/UVALive-4487 带删点的加权并查集 https://vjudge.net/problem/UVA-11 ...

  2. 【Codeforces576E_CF576E】Painting Edges(可撤销并查集+线段树分治)

    题目 CF576E 分析: 从前天早上肝到明天早上qwq其实颓了一上午MC ,自己瞎yy然后1A,写篇博客庆祝一下. 首先做这题之前推荐一道很相似的题:[BZOJ4025]二分图(可撤销并查集+线段树 ...

  3. BZOJ 3910 并查集+线段树合并

    思路: 1. 并查集+线段树合并 记得f[LCA]==LCA的时候 f[LCA]=fa[LCA] 2.LCT(并不会写啊...) //By SiriusRen #include <cstdio& ...

  4. 并查集 + 线段树 LA 4730 Kingdom

    题目传送门 题意:训练指南P248 分析:第一个操作可以用并查集实现,保存某集合的最小高度和最大高度以及城市个数.运用线段树成端更新来统计一个区间高度的个数,此时高度需要离散化.这题两种数据结构一起使 ...

  5. uvalive 4730王国kingdom(并查集+线段树)

     题意:有T组測试数据.每组数据的N表示有N个城市,接下来的N行里每行给出每一个城市的坐标(0<=x,y<=1000000),然后有M(1<M<200000)个操作,操作有 ...

  6. YYHS-猜数字(并查集/线段树维护)

    题目描述     LYK在玩猜数字游戏.    总共有n个互不相同的正整数,LYK每次猜一段区间的最小值.形如[li,ri]这段区间的数字的最小值一定等于xi.     我们总能构造出一种方案使得LY ...

  7. luogu5012 水の数列 (并查集+线段树)

    如果我们能求出来每个区间个数的最大分值,那就可以用线段树维护这个东西 然后出答案了 然后这个的求法和(luogu4269)Snow Boots G非常类似,就是我们把数大小排个序,每次都拿<=x ...

  8. 【CF471E】MUH and Lots and Lots of Segments 扫描线+并查集+线段树+set

    [CF471E]MUH and Lots and Lots of Segments 题意:给你平面上n条水平或竖直的,端点在整点处的线段.你需要去掉一些线段的一些部分,使得剩下的图形:1.连通,2.无 ...

  9. bzoj 3237 连通图 - 并查集 - 线段树

    Input Output Sample Input 4 5 1 2 2 3 3 4 4 1 2 4 3 1 5 2 2 3 2 1 2 Sample Output Connected Disconne ...

随机推荐

  1. vim: vim快捷键

    0. 搜索字符串: 精确匹配查找单词 如果你输入 "/the",你也可能找到 "there". 要找到以 "the" 结尾的单词,可以用:/ ...

  2. html-图片button,抓包---Shinepans

    askLike.html <html> <meta http-equiv="content-type" content="text/html;chars ...

  3. UVA 10494-If We Were a Child Again(一流的塔尔苏斯)

    Problem C If We Were a Child Again Input: standard input Output: standard output  seconds   "Oo ...

  4. Android手势识别(单击 双击 抬起 短按 长按 滚动 滑动)

    对于触摸屏,其原生的消息无非按下.抬起.移动这几种,我们只需要简单重载onTouch或者设置触摸侦听器setOnTouchListener即可进行处理.不过,为了提高我们的APP的用户体验,有时候我们 ...

  5. Android开发系列(二十八):使用SubMenu创建选项菜单

    大部分手机上边都会有一个"MENU"键,在一个应用安装到手机上之后,能够通过"MENU"显示该应用关联的菜单. 可是,从Android 3.0開始,Androi ...

  6. Locally weighted linear regression(局部加权线性回归)

    (整理自AndrewNG的课件,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) 前面几篇博客主要介绍了线性回归的学习算法,那么它有什么不足的地方么 ...

  7. 批处理运行python

    @echo off cd C:\test start python test.py start python test2.py exit

  8. Git Hub,eclipse pull 出现问题

    一般在eclise里面使用geithub,之后会出现无法pull,或者pull 报错的问题.这里需要修改本地库的配置文件 The current branch is not configured fo ...

  9. SetWindowLong

    SetWindowLong函数介绍 收藏 SetWindowLong函数介绍 SetWindowLong Unicode 函数原型 LONG SetWindowLong(hwnd,nIndex,lNe ...

  10. IT行业,需要经常锻炼,开篇从本钱开始

    今天下完班,和部门兄弟一起去打了两小时乒乓球,大汗淋漓,很痛快. 败给了两个高手,感觉年龄大了些,灵活性没有以前那么好了. 想想以前读书时,在整个学校都叱诧风云,如今即败给了几个老手,唉. 看来以后要 ...