题意

规定区间\((a,b)\)到区间\((c,d)\)有边当且仅当\(c<a<d\)或\(c<b<d\)。

起初区间集合为空。有\(n\)(\(n\leq 10^5\))次操作,每次操作形如:

  • \(1\) \(x\) \(y\)(\(|x|,|y|\leq10^9\)):加入一个新区间\((x,y)\),保证新区间长度最长
  • \(2\) \(x\) \(y\):询问第\(i\)个加入第区间能否到达第\(j\)个加入第区间,保证询问合法

题解

考虑连边的两种情况:第一种是包含,小的向大的连边;第二种是相交不包含,连双向边。

注意到答案最后不会走超过\(1\)条单向边,我们先考虑双向边。

由于是双向边,我们可以用并查集维护连通块。那对于一个新区间,我们得考虑它和哪些区间连双向边。

可以使用线段树来做这件事。把区间拆放到\(\log\)个线段树结点上。加新区间连边就把左右端点对应线段树叶子结点到根到路径上所有放的路径都合并掉,然后把标记改成自己。题目给了一个每次加入一个最长区间的限制,这样就保证了新区间不会被包含。复杂度也是对的,每个区间分\(\log\)段,每段加入一次删除一次。

询问就判是同个并查集,或者是包含关系就YES,否则NO。注意一个连通块要维护L和R用于判包含。

时间复杂度\(O(n\alpha(n)\log n)\)

  1. #include <algorithm>
  2. #include <cstdio>
  3. using namespace std;
  4. const int N = 1e5 + 10;
  5. struct node {
  6. int op, l, r;
  7. } a[N];
  8. int q, n, b[N * 2], f[N], L[N], R[N];
  9. inline bool bel(int u, int l, int r) {
  10. return l < u && u < r;
  11. }
  12. int find(int u) {
  13. return u == f[u] ? u : f[u] = find(f[u]);
  14. }
  15. vector<int> vec[N << 2];
  16. void solve(int u, int l, int r, int p, int cur) {
  17. if(vec[u].size()) {
  18. for(int i = 0; i < (int) vec[u].size(); i ++) {
  19. int v = vec[u][i]; v = find(v); f[v] = cur;
  20. L[cur] = min(L[cur], L[v]); R[cur] = max(R[cur], R[v]);
  21. }
  22. vec[u].clear();
  23. vec[u].push_back(cur);
  24. }
  25. if(l == r) return ;
  26. int mid = (l + r) >> 1;
  27. if(p <= mid) solve(u << 1, l, mid, p, cur);
  28. else solve(u << 1 | 1, mid + 1, r, p, cur);
  29. }
  30. void pushe(int u, int l, int r, int ql, int qr, int cur) {
  31. if(l == ql && r == qr) {
  32. vec[u].push_back(cur);
  33. return ;
  34. }
  35. int mid = (l + r) >> 1;
  36. if(qr <= mid) pushe(u << 1, l, mid, ql, qr, cur);
  37. else if(ql > mid) pushe(u << 1 | 1, mid + 1, r, ql, qr, cur);
  38. else {
  39. pushe(u << 1, l, mid, ql, mid, cur);
  40. pushe(u << 1 | 1, mid + 1, r, mid + 1, qr, cur);
  41. }
  42. }
  43. int main() {
  44. scanf("%d", &q);
  45. for(int i = 1; i <= q; i ++) {
  46. scanf("%d%d%d", &a[i].op, &a[i].l, &a[i].r);
  47. if(a[i].op == 1) {
  48. b[++ n] = a[i].l; b[++ n] = a[i].r;
  49. }
  50. }
  51. sort(b + 1, b + n + 1);
  52. n = unique(b + 1, b + n + 1) - b - 1;
  53. int c = 0;
  54. for(int i = 1; i <= q; i ++) {
  55. if(a[i].op == 1) {
  56. a[i].l = lower_bound(b + 1, b + n + 1, a[i].l) - b;
  57. a[i].r = lower_bound(b + 1, b + n + 1, a[i].r) - b;
  58. c ++; f[c] = c; L[c] = a[i].l; R[c] = a[i].r;
  59. solve(1, 1, n, a[i].l, c);
  60. solve(1, 1, n, a[i].r, c);
  61. if(a[i].l < a[i].r - 1) {
  62. pushe(1, 1, n, a[i].l + 1, a[i].r - 1, c);
  63. }
  64. }
  65. if(a[i].op == 2) {
  66. int u = find(a[i].l), v = find(a[i].r);
  67. bool tag = u == v || bel(L[u], L[v], R[v]) || bel(R[u], L[v], R[v]);
  68. puts(tag ? "YES" : "NO");
  69. }
  70. }
  71. return 0;
  72. }

「CF319E」Ping-Pong「线段树」「并查集」的更多相关文章

  1. 【BZOJ4025】二分图(线段树分治,并查集)

    [BZOJ4025]二分图(线段树分治,并查集) 题面 BZOJ 题解 是一个二分图,等价于不存在奇环. 那么直接线段树分治,用并查集维护到达根节点的距离,只计算就好了. #include<io ...

  2. 【CF938G】Shortest Path Queries(线段树分治,并查集,线性基)

    [CF938G]Shortest Path Queries(线段树分治,并查集,线性基) 题面 CF 洛谷 题解 吼题啊. 对于每个边,我们用一个\(map\)维护它出现的时间, 发现询问单点,边的出 ...

  3. BZOJ 4025: 二分图 [线段树CDQ分治 并查集]

    4025: 二分图 题意:加入边,删除边,查询当前图是否为二分图 本来想练lct,然后发现了线段树分治的做法,感觉好厉害. lct做法的核心就是维护删除时间的最大生成树 首先口胡一个分块做法,和hno ...

  4. bzoj2049 线段树 + 可撤销并查集

    https://www.lydsy.com/JudgeOnline/problem.php?id=2049 线段树真神奇 题意:给出一波操作,拆边加边以及询问两点是否联通. 听说常规方法是在线LCT, ...

  5. BZOJ 2333 棘手的操作(离线+线段树+带权并查集)

    这题搞了我一天啊...拍不出错原来是因为极限数据就RE了啊,竟然返回WA啊.我的线段树要开8倍才能过啊... 首先可以发现除了那个加边操作,其他的操作有点像线段树啊.如果我们把每次询问的联通块都放在一 ...

  6. BZOJ 2733 线段树的合并 并查集

    思路: 1.线段树合并(nlogn的) 2.splay+启发式合并 线段树合并比较好写 我手懒 //By SiriusRen #include <cstdio> #include < ...

  7. Explorer(2019年牛客多校第八场E题+线段树+可撤销并查集)

    题目链接 传送门 题意 给你一张无向图,每条边\(u_i,v_i\)的权值范围为\([L_i,R_i]\),要经过这条边的条件是你的容量要在\([L_i,R_i]\),现在问你你有多少种容量使得你可以 ...

  8. 2019牛客暑期多校训练营(第八场) E 线段树+可撤销并查集

    题目传送门 题意: 给出m条无向边,每条边都有一个$[l,r]$,意思是体积在这个范围内的人才能通过这条边,询问有多少种体积的可能性,能使人从1到n 思路:由于是无向边,1和n的连通性可以用并查集维护 ...

  9. BZOJ 2733 [HNOI2012]永无乡 (权值线段树启发式合并+并查集)

    题意: n<=1e5的图里,在线连边.查询某连通块第k大 思路: 练习线段树合并的好题,因为依然记得上一次启发式合并trie的时候内存爆炸的恐怖,所以这次还是用了动态开点.回收 听说启发式合并s ...

  10. 5.29 省选模拟赛 波波老师 SAM 线段树 单调队列 并查集

    LINK:波波老师 LINK:同bzoj 1396 识别子串 不过前者要求线性做法 后者可以log过.实际上前者也被我一个log给水过了. 其实不算很水 我自认跑的很快罢了. 都是求经过一个位置的最短 ...

随机推荐

  1. Codeforces-975C - Valhalla Siege 前缀和 思维

    C. Valhalla Siege time limit per test 2 seconds memory limit per test 256 megabytes input standard i ...

  2. .NET调用腾讯云API实例

    最近项目有用到腾讯云的身份识别接口,话不多说,直接上代码: private void IDCardVerification(HttpContext context) { string imgStr = ...

  3. WSL 服务自动启动

    WSL 服务自动启动 参考 https://zhuanlan.zhihu.com/p/47733615 Windows 启用 WSL 功能支持 > Enable-WindowsOptionalF ...

  4. 【转载】Windows检测到IP地址冲突

    今天在使用电脑的过程中,突然弹出个提示,Windows检测到IP地址冲突,此网络中的另一台计算机与该计算机的IP地址相同.联系你的网络管理员解决此问题,有关详细信息,请参阅Windows系统日志.查阅 ...

  5. 微信开发者工具 关于no such file or directory

    在新建页面中,保存后弹出 “ no such file or directory ” 错误 原因是打开了一个文件,然后在目录树中删除了它,但是这个被删除的页面依旧在打开状态,开发者工具在编译保存时由于 ...

  6. ios9 字符串与UTF-8 互相转换

    在数据网路请求或其他情况下,需要将字符串转换成UTF-8编码 ios9后对其方法进行了修改 NSString *str = @"北京"; 把这个转成UTF8以前我们使用的是 NSS ...

  7. Xshell 上传文件到Ubuntu

    打开Xshell,连上一台Linux服务器或者是虚拟机 如果要方便的上传文件,需要rz 先测试是否安装rz 命令行~$ rz 如果出现未安装(或者command not found)且建议sudo a ...

  8. nodejs库express是如何接收inbound json请求的

    这样几行简单的代码创建一个web服务器: var express = require('express'); var app = express(); var server = require('ht ...

  9. [LeetCode] 95. 不同的二叉搜索树 II ☆☆☆(递归,n个数组成的所有二叉搜索树)

    https://leetcode-cn.com/problems/unique-binary-search-trees-ii/solution/xiang-xi-tong-su-de-si-lu-fe ...

  10. TestNG并发执行用例详解和范例

    前言 TestNG有多种并发方式支持,方法的并发,class级的并发,test级的并发等:根据实际应用可以灵活的配置和使用,下面分别对几种并发方法进行说明: 一.方法级并发 方法级并发即method级 ...