[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 }

 

转载于:https://www.cnblogs.com/kirai/p/6814173.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值