bzoj 1171 并查集优化顺序枚举 | 线段树套单调队列
详见vfleaking在discuss里的题解.
收获: 当我们要顺序枚举一个序列,并且跳过某些元素,那么我们可以用并查集将要跳过的元素合并到一起,这样当一长串元素需要跳过时,可以O(1)跳过.
暴力:
1 /************************************************************** 2 Problem: 1171 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:1908 ms 7 Memory:6732 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <cstring> 12 #define min(a,b) ((a)<(b)?(a):(b)) 13 #define max(a,b) ((a)>(b)?(a):(b)) 14 #define oo 0x3f3f3f3f 15 #define N 250010 16 17 int n, L; 18 int x[N], y[N], d[N]; 19 int dp[N], fa[N], qu[N], bg, ed; 20 21 int find( int i ) { 22 return i==fa[i] ? i : fa[i]=find(fa[i]); 23 } 24 int main() { 25 scanf( "%d%d", &n, &L ); 26 d[1] = 0; 27 x[1] = 0; 28 y[1] = 2000000000; 29 for( int i=2; i<=n; i++ ) 30 scanf( "%d%d%d", x+i, y+i, d+i ); 31 for( int i=1; i<=n; i++ ) 32 fa[i] = i; 33 memset( dp, 0x3f, sizeof(dp) ); 34 35 dp[1] = 0; 36 qu[bg=ed=1] = 1; 37 while( bg<=ed ) { 38 int i=qu[bg++]; 39 for( int j=find(i)+1; j<=n && d[j]-d[i]<=L; j=find(j)+1 ) { 40 if( dp[j]!=oo ) continue; 41 int xx = max( x[i], x[j] ); 42 int yy = min( y[i], y[j] ); 43 if( xx<=yy ) { 44 dp[j] = dp[i]+1; 45 qu[++ed] = j; 46 if( dp[j-1]!=oo ) fa[j-1]=j; 47 if( dp[j+1]!=oo ) fa[j]=j+1; 48 } 49 } 50 } 51 for( int i=2; i<=n; i++ ) 52 printf( "%d\n", dp[i]==oo ? -1 : dp[i] ); 53 }
View Code
线段树套单调队列:
1 #include <cstdio> 2 #include <list> 3 #include <algorithm> 4 #define N 250010 5 #define oo 0x3f3f3f3f 6 using namespace std; 7 8 struct Pair { 9 int d, v; 10 Pair( int d, int v ):d(d),v(v){} 11 }; 12 struct Queue { 13 list<Pair> q; 14 void push( const Pair &p ) { 15 while( !q.empty() && q.back().v >= p.v ) q.pop_back(); 16 q.push_back( p ); 17 } 18 int pop( int d ) { 19 while( !q.empty() && q.front().d<d ) q.pop_front(); 20 return q.empty() ? oo : q.front().v; 21 } 22 }; 23 struct Node { 24 Queue qa, qb; 25 int lf, rg; 26 Node *ls, *rs; 27 void modify( int L, int R, const Pair &p ) { 28 qb.push(p); 29 if( L<=lf && rg<=R ) { 30 qa.push(p); 31 return; 32 } 33 int mid=(lf+rg)>>1; 34 if( L<=mid ) ls->modify(L,R,p); 35 if( R>mid ) rs->modify(L,R,p); 36 } 37 int query( int L, int R, int d ) { 38 if( L<=lf && rg<=R ) return qb.pop(d); 39 int rt = qa.pop(d); 40 int mid=(lf+rg)>>1; 41 if( L<=mid ) { 42 int t = ls->query(L,R,d); 43 rt = min( rt, t ); 44 } 45 if( R>mid ) { 46 int t = rs->query(L,R,d); 47 rt = min( rt, t ); 48 } 49 return rt; 50 } 51 }pool[N*2*3], *tail=pool, *root; 52 53 int n, L; 54 int x[N], y[N], d[N]; 55 int disc[N*2], dtot; 56 57 Node *build( int lf, int rg ) { 58 Node *nd = ++tail; 59 nd->lf=lf, nd->rg=rg; 60 if( lf==rg ) { 61 return nd; 62 } else { 63 int mid=(lf+rg)>>1; 64 nd->ls = build( lf, mid ); 65 nd->rs = build( mid+1, rg ); 66 return nd; 67 } 68 } 69 int main() { 70 scanf( "%d%d", &n, &L ); 71 x[1] = 0; 72 y[1] = 2000000000; 73 disc[++dtot] = x[1]; 74 disc[++dtot] = y[1]; 75 d[1] = 0; 76 for( int i=2; i<=n; i++ ) { 77 scanf( "%d%d%d", x+i, y+i, d+i ); 78 disc[++dtot] = x[i]; 79 disc[++dtot] = y[i]; 80 } 81 sort( disc+1, disc+1+dtot ); 82 dtot = unique( disc+1, disc+1+dtot ) - disc - 1; 83 for( int i=1; i<=n; i++ ) { 84 x[i] = lower_bound( disc+1, disc+1+dtot, x[i] ) - disc; 85 y[i] = lower_bound( disc+1, disc+1+dtot, y[i] ) - disc; 86 } 87 root = build( 1, dtot ); 88 root->modify( x[1], y[1], Pair(0,0) ); 89 for( int i=2; i<=n; i++ ) { 90 int ans = root->query( x[i], y[i], d[i]-L ); 91 if( ans==oo ) { 92 printf( "-1\n" ); 93 } else { 94 ans++; 95 printf( "%d\n", ans ); 96 root->modify( x[i], y[i], Pair(d[i],ans) ); 97 } 98 } 99 }
View Code
转载于:https://www.cnblogs.com/idy002/p/4573846.html
bzoj 1171 并查集优化顺序枚举 | 线段树套单调队列相关推荐
- BZOJ 2143 飞飞侠(线段树优化建边 / 并查集优化最短路)【BZOJ修复工程】
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 题目链接 https://hydro.ac/d/bzoj/p/2143 是 hydro 的 BZOJ ...
- 【割边缩点】解题报告:POJ - 3694 - Network(Tarjan割边缩点 + LCA + 并查集优化)
POJ - 3694 - Network 给定一张N个点M条边的无向连通图,然后执行Q次操作,每次向图中添加一条边,并且询问当前无向图中"桥"的数量.N≤105,M≤2∗105,Q ...
- POJ - 3694 Network(边双缩点+LCA+并查集优化)
题目链接:点击查看 题目大意:给出一个由n个点组成的无向图,现在有m次操作,每次操作都会向图中增加一条无向边,每次操作后询问当前图中有多少个桥 题目分析:题意很好理解,思路也很好想,就是代码量有点小多 ...
- 斜率优化之凸包优化与李超线段树
文章目录 前言 凸包优化 第一步 第二步 最后一步 例一 转移方程 凸包优化 代码 例二 题目大意 转移方程 凸包优化 代码 李超线段树 思想 插入 查询 代码 例三 代码 例四 转移方程 怎么做 代 ...
- In Touch(dijk+并查集优化)
There are n soda living in a straight line. soda are numbered by 1,2,-,n1,2,-,n from left to right. ...
- BZOJ 3910 并查集+线段树合并
思路: 1. 并查集+线段树合并 记得f[LCA]==LCA的时候 f[LCA]=fa[LCA] 2.LCT(并不会写啊...) //By SiriusRen #include <cstdio& ...
- bzoj 1015 并查集
代码: //这题可以反着想,把要去掉的点倒着处理变成往图中一个一个的加点,然后用并查集处理联通快就好了. #include<iostream> #include<cstdio> ...
- 【BZOJ2342】双倍回文,manacher+并查集优化
Time:2016.08.16 Author:xiaoyimi 转载注明出处谢谢 传送门 思路: woc第一次写马拉车怎么这么蛋疼啊 p[i]表示以i为中点,能向增长的最多的回文长度的一半 比如&qu ...
- bzoj 2054 并查集
题意:给定一个序列,多次将某个区间染成某种颜色,求最后每个点是什么颜色 由于只求最后染的颜色,所以倒着染 这样一个位置最多只需要染一次,染过就不需要再染 也就是说,对于当前染色,区间内已经染色的位置这 ...
- bzoj 3563 ╮(╯▽╰)╭+ 并查集
题意:N个点,M条无向边,Q个操作,每个操作中破坏K条边,其中编号和K已经加密,即原数异或之前未联通的个数(给的是原k,但后面有异或后的k的个数个编号),判断每个操作后是否联通 会做题不等于会出题系列 ...
最新文章
- 从内存溢出看Java 环境中的内存结构
- ZOJ 1410 题解
- JQuery选择器——基本筛选选择器和内容筛选选择器
- SAP系统硬件解决方案
- JQuery .net WebService 参数必须一致
- tomcat——轻量级中间件学习
- c语言程序设计 简述操作系统管理文件的方法,C语言程序设计基础实验.doc
- Linux之32/64位int、char、int*、char*与空结构体大小
- 学校计算机考试系统故障,解决在线考试系统设计的常见问题
- 有效值(RMS) 平均值(DC) 的理解
- 2021鹏业安装算量软件常见问题整理(四)
- 用GNS3制作路由交换网络拓扑图
- 安卓开发 投屏安卓设备到电脑端 scrcpy
- 数据库范式:1NF、2NF、3NF、BCNF
- 删除计算机系学生(在student表中),数据库原理及应用(第2版)习题参考答案
- Windows 安装MySQL 8.0 超详细教程(mysql 8.0.30)
- 【JY】浅谈结构设计
- 网络七层模型与物联网三层模型
- 湎计算机网络通讯设备有哪些,计算机网络习题集及答案.pdf
- 机遇来了!43天之后粤港澳大湾区终于...
热门文章
- xtrabackup备份还原的具体操作过程
- [转]OOPC:Object-Oriented Programming in C
- ubuntu 13.04 web开发从零配置到全装备手记(环境搭建全攻略)
- 推荐第三方SQL查询工具
- License Server Version 11.9 Installation on Windows Server 2003 Hangs
- java反射集合类_java反射 - lara - OSCHINA - 中文开源技术交流社区
- endnotex7怎么导入中文文献,EndNote 7.0使用中文详细教程
- 新学到的Url形成方法
- [渝粤教育] 江西理工大学 新融合大学英语(I) 参考 资料
- 【渝粤教育】国家开放大学2019年春季 0755-22T学前儿童艺术教育 参考试题