HDU5091->线段树维护区间覆盖次数&&扫描线
2016-08-20 12:14
387 查看
HDU5091->线段树维护区间覆盖次数&&扫描线
题意:一个平面上有一些点,给出这些点的坐标,求用一个宽为w高为h的格子最多能包含到多少个点
题解:
用一根平行于y轴的扫描线维护沿x轴方向的宽度,而沿y轴方向的点的个数的计算则可以等价为求一个区间内线段覆盖的最多次数。
由于已经给出高度h,所以每个点都可以看成是以这个点的y坐标为起始,长度为h的一条线段。
这里扫描线的运用,就是把一个点拆分成两个点,一个点的x坐标为其原有的x值,这个点为入点,记其flag为1,另一个点的x坐标为x+w,这个点为出点,记其flag为-1
代码:
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define MAX 20005 struct Node { int x , y1 , y2 , flag ; }node[MAX]; struct Tree { int l , r , Ma , lazy ; }tree[MAX << 2]; int y[MAX] ; bool comp(const struct Node a , const struct Node b) { if(a.x == b.x) return a.flag > b.flag ; return a.x < b.x ; } void build(int p , int l , int r) { tree[p].l = y[l] ; tree[p].r = y[r] ; tree[p].Ma = 0 ; tree[p].lazy = 0 ; if(l == r) return ; int mid = (l + r) >> 1 ; build(p << 1 , l , mid) ; build(p << 1 | 1 , mid + 1 , r) ; } void Pushdown(int p) { if(tree[p].lazy != 0) { tree[p << 1].lazy += tree[p].lazy ; tree[p << 1].Ma += tree[p].lazy ; tree[p << 1 | 1].lazy += tree[p].lazy ; tree[p << 1 | 1].Ma += tree[p].lazy ; tree[p].lazy = 0 ; } } void update(int p , int l , int r , int y1 , int y2 , int flag) { if(y1 <= tree[p].l &&y2 >= tree[p].r) { tree[p].Ma += flag ; tree[p].lazy += flag ; return ; } Pushdown(p) ; int mid = (l + r) >> 1 ; if(y2 <= y[mid]) update(p << 1 , l , mid , y1 , y2 , flag) ; else if(y1 > y[mid]) update(p << 1 |1 , mid + 1 , r , y1 , y2 , flag) ; else { update(p <<1 , l , mid , y1 , y[mid] , flag) ; update(p << 1 | 1 , mid + 1 , r , y[mid+ 1] , y2 , flag) ; } tree[p].Ma = max(tree[p<< 1].Ma , tree[p << 1 | 1].Ma) ; } int main() { int n , w , h ; while(~scanf("%d" , &n) , n>0) { scanf("%d%d" , &w , &h) ; for(int i = 0 ; i < n ; i ++) { int x0 , y0 ; scanf("%d%d" , &x0 , &y0) ; node[i].x = x0 ; node[i].y1 = y0 ; node[i].y2 = y0 + h ; node[i].flag = 1 ; y[i+1] = y0 ; node[n+i].x = x0 +w ; node[n+i].y1 = y0 ; node[n+i].y2 = y0 + h ; node[n+i].flag = -1 ; y[n+i+1] = y0 + h ; } sort(node , node + 2*n , comp) ; sort(y+1 , y + 1 + n*2) ; int cnt = unique(y+1 , y + 2*n + 1) - y - 1 ; build(1 , 1 , cnt) ; int ans = 0 ; for(int i = 0 ; i < 2*n ; i ++) { update(1 , 1 , cnt , node[i].y1 , node[i].y2 , node[i].flag) ; ans = max(ans , tree[1].Ma) ; } printf("%d\n" , ans) ; } return 0; }
相关文章推荐
- 20140920 【 线段树 — 区间覆盖,区间查询 】 2014 ACM/ICPC Asia Regional Guangzhou Online--A Corrupt Mayor's Perfor
- poj 3667 Hotel 找最左面连续区间>=need的区间 线段树
- UVa 11235 / POJ 3368 Frequent values (想法题&RMQ线段树维护最长区间长度)
- hdoj 3397 Sequence operation 【线段树区间覆盖 + 异或 + 合并】【维护延迟标记的顺序】
- POJ 3667 Hotel(线段树:区间覆盖,维护最大连续子区间)
- HDU 3577 Fast Arrangement(线段树功能:区间更新,查询区间的最大覆盖次数)
- hdu 3577 线段树,成段更新 好题 查询区间的最大覆盖次数
- POJ 2528 Mayor's posters 线段树的区间覆盖 离散化
- 【线段树维护区间编号 && 区间更新】HDU - 4614 Vases and Flowers
- ZOJ 3686 A Simple Tree Problem(将对树的操作转化成区间=>线段树)
- hdu 5023 A Corrupt Mayor's Performance Art 广州网络赛 线段树的区间覆盖+种类查询
- poj 2528 Mayor's posters(扫描线+堆维护||离散化+线段树)
- 2528 Mayor's posters 线段树的覆盖问题 判断一段区间是否被覆盖
- HDU 3577 Fast Arrangement ( 线段树 成段更新 区间最值 区间最大覆盖次数 )
- poj 2528 Mayor's posters(线段树区间覆盖、离散化)
- Screensaver<用线段树维护函数系数>
- 【维护区间最长连续子序列 && 线段树 && 区间归并】HDU - 1540 Tunnel Warfare
- hdu 1754 I Hate It ----->线段树(区间最值,单点更新)
- <转> 线段树区间并
- whu 1464 Deal whth Numbers 线段树维护区间除法