题目传送门

题意:训练指南P248

分析:第一个操作可以用并查集实现,保存某集合的最小高度和最大高度以及城市个数。运用线段树成端更新来统计一个区间高度的个数,此时高度需要离散化。这题两种数据结构一起使用,联系紧密。

#include <bits/stdc++.h>
using namespace std; const int N = 1e5 + 5;
const int M = 3 * N;
const int INF = 0x3f3f3f3f;
struct Point {
int x, y;
Point() {}
Point(int x, int y) : x (x), y (y) {}
};
struct Query {
int op;
int u, v, w;
}q[2*N]; #define lson l, mid, o << 1
#define rson mid + 1, r, o << 1 | 1
int city[M<<2], num[M<<2], col[M<<2], col2[M<<2]; //Segment_Tree
void push_down(int o) {
if (col[o]) {
col[o<<1] += col[o]; col[o<<1|1] += col[o];
city[o<<1] += col[o]; city[o<<1|1] += col[o];
col[o] = 0;
}
if (col2[o]) {
col2[o<<1] += col2[o]; col2[o<<1|1] += col2[o];
num[o<<1] += col2[o]; num[o<<1|1] += col2[o];
col2[o] = 0;
}
}
void build(int l, int r, int o) {
col[o] = 0; col2[o] = 0;
if (l == r) {
city[o] = num[o] = 0;
return ;
}
int mid = l + r >> 1;
build (lson); build (rson);
}
void updata(int ql, int qr, int c1, int c2, int l, int r, int o) {
if (ql <= l && r <= qr) {
col[o] += c1; col2[o] += c2;
city[o] += c1; num[o] += c2;
return ;
}
push_down (o);
int mid = l + r >> 1;
if (ql <= mid) updata (ql, qr, c1, c2, lson);
if (qr > mid) updata (ql, qr, c1, c2, rson);
}
void query(int p, int l, int r, int o) {
if (l == r && l == p) {
printf ("%d %d\n", city[o], num[o]); return ;
}
push_down (o);
int mid = l + r >> 1;
if (p <= mid) query (p, lson);
else query (p, rson);
} int n, m, bound; int rt[N], rk[N], maxy[N], miny[N]; //DSU
void init(void) {
memset (rt, -1, sizeof (rt));
memset (rk, 0, sizeof (rk));
}
int Find(int x) {
return rt[x] == -1 ? x : rt[x] = Find (rt[x]);
}
void Union(int u, int v) {
u = Find (u); v = Find (v);
if (u == v) return ;
if (rk[u] > rk[v]) swap (u, v);
if (rk[u]) updata (miny[u], maxy[u], -1, -(rk[u] + 1), 1, bound, 1);
if (rk[v]) updata (miny[v], maxy[v], -1, -(rk[v] + 1), 1, bound, 1); maxy[v] = max (maxy[v], maxy[u]);
miny[v] = min (miny[v], miny[u]); rt[u] = v; rk[v] += rk[u] + 1;
rk[u] = 0;
updata (miny[v], maxy[v], 1, rk[v] + 1, 1, bound, 1);
} Point point[N];
vector<int> ys; void run(void) {
init (); build (1, bound, 1);
for (int i=1; i<=n; ++i) {
miny[i] = maxy[i] = point[i].y;
}
for (int i=1; i<=m; ++i) {
if (q[i].op == 0) {
Union (q[i].u, q[i].v);
}
else {
query (q[i].w, 1, bound, 1);
}
}
} int main(void) {
int T; scanf ("%d", &T);
while (T--) {
scanf ("%d", &n);
int x, y;
ys.clear ();
for (int i=1; i<=n; ++i) {
scanf ("%d%d", &x, &y); point[i] = Point (x, 2 * y);
ys.push_back (point[i].y);
}
char str[10];
int u, v; double t;
scanf ("%d", &m);
for (int i=1; i<=m; ++i) {
scanf ("%s", &str);
if (str[0] == 'r') {
scanf ("%d%d", &u, &v);
q[i].op = 0; q[i].u = u + 1, q[i].v = v + 1;
}
else if (str[0] == 'l') {
scanf ("%lf", &t);
q[i].op = 1; q[i].w = (int) (2 * t);
ys.push_back (q[i].w);
}
}
sort (ys.begin (), ys.end ());
ys.erase (unique (ys.begin (), ys.end ()), ys.end ());
bound = 200010;
for (int i=1; i<=n; ++i) {
point[i].y = lower_bound (ys.begin (), ys.end (), point[i].y) - ys.begin () + 1;
}
for (int i=1; i<=m; ++i) {
if (q[i].op == 1) {
q[i].w = lower_bound (ys.begin (), ys.end (), q[i].w) - ys.begin () + 1;
}
}
run ();
} return 0;
}

  

并查集 + 线段树 LA 4730 Kingdom的更多相关文章

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

    UVA1455 - Kingdom(并查集 + 线段树) 题目链接 题目大意:一个平面内,给你n个整数点,两种类型的操作:road x y 把city x 和city y连接起来,line fnum ...

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

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

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

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

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

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

  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. 如何查看设备的 UDID

    手机连接上电脑,打开 Xcode,确认手机已连上: command+shift+2,就可以查看到 UDID 了:

  2. August 30th 2016 Week 36th Tuesday

    If you keep on believing, the dreams that you wish will come true. 如果你坚定信念,就能梦想成真. I always believe ...

  3. July 5th, Week 28th Tuesday, 2016

    If you smile when no one else is around, you really mean it. 独处的时候你的笑容才是发自内心的笑容. Human beings are so ...

  4. CABasicAnimation 按home键后台之后,再切回来动画就停止了

    解决方法: 1. CABasicAnimation *thisAnimation = [CABasicAnimtaion animationWithKeyPath:@"transform.r ...

  5. route命令

    Linux系统的route 命令用于显示和操作IP路由表(show / manipulate the IP routing table).要实现两个不同的子网之间的通信,需要一台连接两个网络的路由器, ...

  6. Mac 下查看 Android Studio 的 SHA1的方法

    cmd -> ->cd .android ->keytool -v -list -keystore debug.keystore 默认口令:android ************* ...

  7. Linq学习笔记---Linq to Xml操作

    LINQ to XML的成员, 属性列表: 属性 说明 Document 获取此 XObject 的 XDocument  EmptySequence  获取空的元素集合  FirstAttribut ...

  8. MongoDB基本命令

    1.  启动和停止MongoDB: 执行mongod命令启动MongoDB服务器.mongod有很多可配置的选项,我们通过mongod --help可以查看所有选项,这里仅介绍一些主要选项:    - ...

  9. C++ 内联函数笔记

    要使用内联函数,必须采取下述措施之一: +在函数声明前加上关键字inline: +在函数定义前加上关键字inline. 通常的做法是省略原型,将整个定义(即函数头和所有函数代码)放在本应提供原型的地方 ...

  10. css2

    CSS 实现div宽度根据内容自适应 <!DOCTYPE html> <html> <head> <meta charset="utf-8" ...