题意:

平面上有\(n\)个点,有一种操作和一种查询:

  • \(road \, A \, B\):在\(a\),\(b\)两点之间加一条边
  • \(line C\):询问直线\(y=C\)经过的连通分量的个数以及这些连通分量点的总数

分析:

其实横坐标是没用的,首先可以先将纵坐标离散化。

用并查集维护点的连通性,连通分量的大小以及连通分量中纵坐标的最大值和最小值。

线段树中维护的是每条直线穿过的连通分量的个数以及点的个数之和。

当两个连通分量合并时,先把两个小连通分量从线段树中删去,然后再把合并之后的大连通分量加进去。

修改是区间修改,查询是单点查询。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = 100000 + 10;
const int maxnode = maxn * 4; int n;
int a[maxn], tot, b[maxn]; int pa[maxn], sz[maxn], miny[maxn], maxy[maxn];
int findset(int x) { return x == pa[x] ? x : pa[x] = findset(pa[x]); } int states[maxnode], cities[maxnode]; char cmd[15]; void pushdown(int o, int* add) {
if(add[o] != 0) {
add[o<<1] += add[o];
add[o<<1|1] += add[o];
add[o] = 0;
}
} void pushdown(int o) {
pushdown(o, states);
pushdown(o, cities);
} void update(int o, int L, int R, int qL, int qR, int v1, int v2) {
if(qL <= L && R <= qR) {
states[o] += v1;
cities[o] += v2;
return;
}
pushdown(o);
int M = (L + R) / 2;
if(qL <= M) update(o<<1, L, M, qL, qR, v1, v2);
if(qR > M) update(o<<1|1, M+1, R, qL, qR, v1, v2);
} void query(int o, int L, int R, int pos) {
if(L == R) {
printf("%d %d\n", states[o], cities[o]);
return;
}
pushdown(o);
int M = (L + R) / 2;
if(pos <= M) query(o<<1, L, M, pos);
else query(o<<1|1, M+1, R, pos);
} int main()
{
int T; scanf("%d", &T);
while(T--) {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
pa[i] = i; sz[i] = 1;
int x; scanf("%d%d", &x, a + i);
b[i - 1] = a[i];
}
sort(b, b + n);
tot = unique(b, b + n) - b;
for(int i = 1; i <= n; i++) {
a[i] = lower_bound(b, b + tot, a[i]) - b;
miny[i] = maxy[i] = a[i];
} memset(states, 0, sizeof(states));
memset(cities, 0, sizeof(cities));
int m; scanf("%d", &m);
while(m--) {
scanf("%s", cmd);
if(cmd[0] == 'r') {
int a, b; scanf("%d%d", &a, &b);
a++; b++;
int fa = findset(a), fb = findset(b);
if(fa == fb) continue;
int L = miny[fa], R = maxy[fa];
if(L < R) update(1, 1, n, L + 1, R, -1, -sz[fa]);
L = miny[fb], R = maxy[fb];
if(L < R) update(1, 1, n, L + 1, R, -1, -sz[fb]);
//Union
pa[fb] = fa;
sz[fa] += sz[fb];
miny[fa] = min(miny[fa], miny[fb]);
maxy[fa] = max(maxy[fa], maxy[fb]);
L = miny[fa], R = maxy[fa];
if(L < R) update(1, 1, n, L + 1, R, 1, sz[fa]);
} else {
double ty; scanf("%lf", &ty);
int y = (int)ty + 1;
y = lower_bound(b, b + tot, y) - b;
query(1, 1, n, y);
}
}
} return 0;
}

UVa 1455 Kingdom 线段树 并查集的更多相关文章

  1. [WC2005]双面棋盘(线段树+并查集)

    线段树+并查集维护连通性. 好像 \(700ms\) 的时限把我的常数超级大的做法卡掉了, 必须要开 \(O_2\) 才行. 对于线段树的每一个结点都开左边的并查集,右边的并查集,然后合并. \(Co ...

  2. 2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集)

    2022.02.27 CF811E Vladik and Entertaining Flags(线段树+并查集) https://www.luogu.com.cn/problem/CF811E Ste ...

  3. 【CF687D】Dividing Kingdom II 线段树+并查集

    [CF687D]Dividing Kingdom II 题意:给你一张n个点m条边的无向图,边有边权$w_i$.有q个询问,每次给出l r,问你:如果只保留编号在[l,r]中的边,你需要将所有点分成两 ...

  4. 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集

    3673: 可持久化并查集 by zky Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 1878  Solved: 846[Submit][Status ...

  5. 【XSY2707】snow 线段树 并查集

    题目描述 有\(n\)个人和一条长度为\(t\)的线段,每个人还有一个工作范围(是一个区间).最开始整条线段都是白的.定义每个人的工作长度是这个人的工作范围中白色部分的长度(会随着线段改变而改变).每 ...

  6. bzoj 2054: 疯狂的馒头(线段树||并查集)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2054 线段树写法: 点的颜色只取决于最后一次染的颜色,所以我们可以倒着维护,如果当前区间之前 ...

  7. 【BZOJ1453】[Wc]Dface双面棋盘 线段树+并查集

    [BZOJ1453][Wc]Dface双面棋盘 Description Input Output Sample Input Sample Output HINT 题解:话说看到题的第一反应其实是LCT ...

  8. codeforces 811E Vladik and Entertaining Flags(线段树+并查集)

    codeforces 811E Vladik and Entertaining Flags 题面 \(n*m(1<=n<=10, 1<=m<=1e5)\)的棋盘,每个格子有一个 ...

  9. 【Codeforces811E】Vladik and Entertaining Flags [线段树][并查集]

    Vladik and Entertaining Flags Time Limit: 20 Sec  Memory Limit: 512 MB Description n * m的矩形,每个格子上有一个 ...

随机推荐

  1. JMeter测试TCP服务器遇到的一个奇怪问题

    今天工作需要测TCP服务器的压力,因为tsung测试TCP需要写的脚本实在头大,于是换了JMETER来搞压力测试.在实际测试的过程中,遇到了一个很奇怪的问题,就是发了数据包以后,JMeter不停地报5 ...

  2. 在spark2中的shell使用python3

    在spark2中的shell使用python3 spark2.0.0中的python默认使用python2,可以通过以下两种方式之一使用python3: PYSPARK_PYTHON=python3 ...

  3. Linux系统 Centos7/Centos6.8 yum命令在线安装 MySQL5.6

    Linux系统 Centos7 yum命令在线安装 MySQL5.6 标签: centosmysqlyum 2015-11-18 17:21 707人阅读 评论(0) 收藏 举报  分类: Linux ...

  4. Ubuntu 安装boost 库

    使用 apt-get进行安装 sudo apt-get install libboost-dev

  5. logback的configuration

    logback的<configuration>只有三个属性: 1.scan[boolean]:当scan被设置为true时,当配置文件发生改变,将会被重新加载.默认值为true. 2.sc ...

  6. wechat开发笔记之1.接口示例代码

    修改后的php示例代码! <?php /** * wechat php test */ //define your token define("TOKEN", "w ...

  7. IDA逆向:结构体的逆向

    源代码: int _tmain(int argc, _TCHAR* argv[]) { struct v1 { int a; short b; char c; int d; double e; }; ...

  8. pat乙级1045

    从左到右扫描时记录扫描到当前下标为止的最大值,如果当前元素大于这个最大值,那么它就大于它左边的所有值.同理,从右到左扫描记录扫描到当前下标为止的最小值,如果当前元素小于这个最大小值,那么它就小于它右边 ...

  9. HBuilder发行App(Android和ios)

    怎样将开发好的app测试和上架,此文包括Android和ios打包.测试和上架的大概过程.内容有些简陋,因为此过程踏坑无数,特此留念. 特此声明:内容不全仅供参考. 介绍两个参考网站: 1. http ...

  10. UVALive 4987 EvacuationPlan(dp,贪心)

    在所有避难所都有至少一只队伍的情况,总移动距离最小. 把队伍的位置和人都排序. 会发现,对于最后一个队伍i和最后一个避难所j, Case 1:pos[j]>=pos[i],那么i是距离j最近的一 ...