[HDOJ5091]Beam Cannon(贪心,线段树,扫描线,矩形内覆盖最多点)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5091
题意:给个W*H的矩形和n个点,问这个矩形最多能框住多少个点。
将每一个点(x,y)扩展为(x,y)、(x+W,y+H)的矩形跑扫描线。
变成了一个区间累加更新,查询最值的问题。
这个画画图就能想出来,因为贪心地想,一定是把一个点放到矩形的角上再向周围框,能框到最多。所以就利用了这一条贪心性质。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define lrt rt << 1 5 #define rrt rt << 1 | 1 6 typedef struct Seg { 7 int add, val; 8 }Seg; 9 typedef struct Event { 10 int l, r, h, sign; 11 }Event; 12 const int maxn = 40200; 13 int n, w, h, ret; 14 int hh[maxn], hcnt; 15 vector<Event> event; 16 Seg seg[maxn<<2]; 17 18 bool cmp(Event a, Event b) { 19 if(a.h != b.h) return a.h < b.h; 20 return a.sign > b.sign; 21 } 22 23 void build(int l, int r, int rt) { 24 seg[rt].val = seg[rt].add = 0; 25 if(l == r) return; 26 int mid = (l + r) >> 1; 27 build(l, mid, lrt); 28 build(mid+1, r, rrt); 29 } 30 31 32 void pushup(int rt) { 33 seg[rt].val = max(seg[lrt].val, seg[rrt].val); 34 } 35 36 void pushdown(int rt) { 37 if(seg[rt].add) { 38 seg[lrt].add += seg[rt].add; 39 seg[lrt].val += seg[rt].add; 40 seg[rrt].add += seg[rt].add; 41 seg[rrt].val += seg[rt].add; 42 seg[rt].add = 0; 43 } 44 } 45 46 void update(int L, int R, int sign, int l, int r, int rt) { 47 if(L <= l && r <= R) { 48 seg[rt].add += sign; 49 seg[rt].val += sign; 50 return; 51 } 52 pushdown(rt); 53 int mid = (l + r) >> 1; 54 if(L <= mid) update(L, R, sign, l, mid, lrt); 55 if(mid < R) update(L, R, sign, mid+1, r, rrt); 56 pushup(rt); 57 } 58 59 int id(int x) { 60 return lower_bound(hh, hh+hcnt, x) - hh + 1; 61 } 62 63 int main() { 64 // freopen("in", "r", stdin); 65 int x, y; 66 while(~scanf("%d",&n) && n >= 0) { 67 scanf("%d%d",&w,&h); 68 event.clear(); hcnt = 0; 69 for(int i = 0; i < n; i++) { 70 scanf("%d%d",&x,&y); 71 event.push_back(Event{x, x+w, y, 1}); 72 event.push_back(Event{x, x+w, y+h, -1}); 73 hh[hcnt++] = x, hh[hcnt++] = x + w; 74 } 75 sort(event.begin(), event.end(), cmp); 76 sort(hh, hh+hcnt); hcnt = unique(hh, hh+hcnt) - hh; 77 build(1, hcnt, 1); 78 ret = 0; 79 for(int i = 0; i < event.size(); i++) { 80 int l = id(event[i].l); 81 int r = id(event[i].r); 82 int sign = event[i].sign; 83 update(l, r, sign, 1, hcnt, 1); 84 ret = max(ret, seg[1].val); 85 } 86 printf("%d\n", ret); 87 } 88 return 0; 89 }