POJ 2528 线段树 成段更新+【离散化】 贴海报.cpp
题意:
给出了n份海报的贴在board上的起始位置和结束位置
问最后可以看到多少份海报
输入:
n表示有n份海报
接下来n行 每行 a b 表示海报占据了a~b的位置..
思路:
线段树成段更新
用树的结点value表示控制范围内的海报编号..
因为不用更新到底+查询到每一个叶子节点..所以提高了查询和更新效率..
其中因为海报长度给的很大..
所以可以使用离散化来减少空间的消耗以及查询和更新时的递归次数..
Tips:
因为给出的a b 表示的是在a~b内贴了海报..
所以a b给的是值..但是表示的是一段范围..
如果用正常的离散化..就可能出现
最底下一层贴了一张海报AA..
然后上面贴了两张相邻的海报BB 和 CC
BB.r < CC.l
但是离散化后因为BB和CC是相邻的..所以BB.r = CC.l
这样~本来两张海报之间是有空隙的..可以透过空隙看到AA
结果离散化之后就覆盖了那个空隙..
解决方法就是当发现相隔的两个海报之间的距离>1就在中间加一个数..
离散化的处理方式很有趣吖~~^^
1 for(i = 0; i < n; ++i) { 2 scanf("%d %d", &l, &r); 3 if(vis[l] == 0){//如果没有访问过这个点.. 4 vis[l] = 1; 5 s[tot++] = l;//就把这个点加到离散化的数组里.. 6 } 7 if(vis[r] == 0) { 8 s[tot++] = r; 9 vis[r] = 1; 10 } 11 node[i].l = l, node[i].r = r; 12 } 13 14 sort(s, s+tot); 15 16 for(i = tot-1; i > 0; --i) {//在相邻的海报间增加一个点 17 if(s[i] - s[i-1] > 1) 18 s[tot++] = s[i-1]+1; 19 } 20 sort(s, s+tot); 21 22 for(i = 0; i < n; ++i) {//s数组的下标就是离散化后的值.. 23 l = solve(node[i].l, tot, s); 24 r = solve(node[i].r, tot, s); 25 modify(l, r, i, 0, tot, 1); 26 } 27 28 29 int solve(int key, int tot, int *arr) 30 { 31 int mid; 32 int l = 0, r = tot-1; 33 while(l <= r) { 34 mid = (l+r)>>1; 35 if(arr[mid] == key) return mid; 36 if(arr[mid] > key) r = mid-1; 37 else l = mid+1; 38 } 39 }
还有问题就是if(vis[r] == 0) 有时候 r 会很大..这样写就错了~
所以可以不管有没有增加过这个点都先放入 s 数组里~
然后再去重..
Code:
1 #include <stdio.h> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 const int MAXN = 40010; 7 int lazy[MAXN<<2]; 8 int arr[MAXN]; 9 int vis[10000010]; 10 int s[MAXN]; 11 int cnt; 12 13 struct Node 14 { 15 int r; 16 int l; 17 }node[MAXN]; 18 19 void pushDown(int rt) 20 { 21 if(lazy[rt] != -1) { 22 lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt]; 23 lazy[rt] = -1; 24 } 25 } 26 27 void modify(int l, int r, int x, int L, int R, int rt) 28 { 29 if(l <= L && r >= R) { 30 lazy[rt] = x; 31 return; 32 } 33 pushDown(rt); 34 int mid = (L+R) >> 1; 35 if(l <= mid) modify(l, r, x, L, mid, rt<<1); 36 if(mid < r) modify(l, r, x, mid+1, R, rt<<1|1); 37 } 38 39 int solve(int key, int tot, int *arr) 40 { 41 int mid; 42 int l = 0, r = tot-1; 43 while(l <= r) { 44 mid = (l+r)>>1; 45 if(arr[mid] == key) return mid; 46 if(arr[mid] > key) r = mid-1; 47 else l = mid+1; 48 } 49 } 50 51 void query(int l, int r, int rt) 52 { 53 if(lazy[rt] != -1) { 54 if(vis[lazy[rt]] == 0) 55 cnt++; 56 vis[lazy[rt]] = 1; 57 return; 58 } 59 if(l == r) return; 60 int mid = (l+r)>>1; 61 query(l, mid, rt<<1); 62 query(mid+1, r, rt<<1|1); 63 } 64 65 int main() 66 { 67 int i, j, k; 68 int n, T; 69 int tot, l, r; 70 while(scanf("%d", &T) != EOF) 71 while(T--) 72 { 73 memset(vis, 0, sizeof(vis)); 74 memset(lazy, 0xff, sizeof(lazy)); 75 tot = cnt = 0; 76 77 scanf("%d", &n); 78 for(i = 0; i < n; ++i) { 79 scanf("%d %d", &l, &r); 80 if(vis[l] == 0){ 81 vis[l] = 1; 82 s[tot++] = l; 83 } 84 if(vis[r] == 0) { 85 s[tot++] = r; 86 vis[r] = 1; 87 } 88 node[i].l = l, node[i].r = r; 89 } 90 91 sort(s, s+tot); 92 93 for(i = tot-1; i > 0; --i) { 94 if(s[i] - s[i-1] > 1) 95 s[tot++] = s[i-1]+1; 96 } 97 sort(s, s+tot); 98 99 for(i = 0; i < n; ++i) { 100 l = solve(node[i].l, tot, s); 101 r = solve(node[i].r, tot, s); 102 modify(l, r, i, 0, tot, 1); 103 } 104 memset(vis, 0, sizeof(vis)); 105 query(0, tot, 1); 106 printf("%d\n", cnt); 107 } 108 return 0; 109 }
题目链接:http://poj.org/problem?id=2528
转载于:https://www.cnblogs.com/Griselda/archive/2012/10/26/2740527.html
POJ 2528 线段树 成段更新+【离散化】 贴海报.cpp相关推荐
- uscao 线段树成段更新操作及Lazy思想(POJ3468解题报告)
线段树成段更新操作及Lazy思想(POJ3468解题报告) 标签: treequerybuildn2cstruct 2011-11-03 20:37 5756人阅读 评论(0) 收藏 举报 分类: ...
- HDOJ 1698 Just a Hook(线段树成段更新)
题意: 屠夫的钩子区间是1~n,每段可能由铜,银,金组成,价值分别为1,2,3,进行一系列的更新之后,求钩子的总价值. 思路: 线段树的成段更新:要设置一个临时的线段树,每次更新的时候把更新段的值放在 ...
- HDU 3974 Assign the task(dfs时间戳+线段树成段更新)
题意:给定点的上下级关系,规定假设给i分配任务a.那么他的全部下属.都停下手上的工作,開始做a. 操作 T x y 分配x任务y,C x询问x的当前任务: Sample Input 1 5 4 3 3 ...
- Wikioi 1081 线段树成段更新单点查询
线段树练习飘逸的写法,自从自己改成这样的写法之后,线段树就没再练过,如今最终练得上了. 由于这里查询仅仅是查询了叶子结点,所以pushUp函数就用不上了,只是我没去掉之前是3ms.去掉之后反而变成4m ...
- UVA 12501 Bulky process of bulk reduction ——(线段树成段更新)
和普通的线段树不同的是,查询x~y的话,给出的答案是第一个值的一倍加上第二个值的两倍一直到第n个值的n倍. 思路的话,就是关于query和pushup的方法.用一个新的变量sum记录一下这个区间里面按 ...
- HDU 6203 ping ping ping lca 线段树成段更新
题目链接:HDU 6203 ping ping ping Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K ( ...
- POJ3468 A Simple Problem with Integers【线段树 成段更新+求和 lazy标志】
用longlong替换__int64也成. #define LL long long 输入输出用%lld Problem: 3468 User: qq1203456195 Memory: 4284 ...
- HDU 3397 Sequence operation 线段树 成段更新 区间合并
比较综合的题. 两个标记 setv,xorr.setv的优先级高于xorr,当一个节点获得一个setv时,他之前的xorr要清除. //#pragma comment(linker, "/ ...
- hdu 1698 线段树成段更新
这么重要的数据结构还是得学啊.仿notonlysuccess的代码风格 #include <cstdio> #include <algorithm> #include < ...
- POJ - 2528 线段树+离散化
其实很早就在白书上的常用技巧上 看到离散化的操作,但是之前一直没遇到过需要离散化的题目(应该是我太菜的缘故),所以一直也没怎么重视,下面说说这道题目的考点,也就是离散化. 什么是离散化呢?请先自行百度 ...
最新文章
- [Google Guava] 1.5-Throwables:简化异常和错误的传播与检查
- 长方形与圆最近连线LISP_编写一个AutoLISP程序,画出一个边长为A的正方形,以及该正方形的内切圆,正方形的底边与正X轴的夹角为ANG...
- 阿里巴巴集团2014秋季校园招聘笔试题
- b站的服务器在哪个位置,b站用的是哪个云服务器
- (转)关于X64位系统IIS7下支持32位asp.net程序
- [Vue.js]实战 -- 电商项目(七)
- 高级php进修,PHP进修笔记一:PHP的数据类型与常量应用
- 特征向量的辨析(数学,机器学习)
- mysql rs.next_JDBC结果集rs.next()注意事项
- 四边形可以分为几类_“平行四边形法则”:谁总结这么奇异的书法规律?
- uniapp微信支付方案
- 常用数据分析方法:方差分析怎么做?
- 周志华 机器学习ppt
- SP商BI平台(MP子平台)——通信增值业务运营SP公司
- 服务器怎么用ftp传文件夹吗,ftp服务器怎么传文件夹吗
- 打印端口用计算机名,如何设置打印机端口,教您设置电脑打印机端口
- S7-1200PLC定时器计数器的应用
- 一个能够自动给pdf生成目录的东西
- 快应用中心运营平台项目心得
- SLCP验厂辅导,企业在认证之后便可以将经验证过后的数据信息分享给其它各托管平台