线段树+扫描线 HDOJ 5091 Beam Cannon

 

题目传送门

 1 /*  2  题意:给出若干个点的坐标,用一个矩形去覆盖,问最多能覆盖几个点  3  线段树+扫描线:思路是先建一棵以[y, y + h]的树,左右儿子[x, x + w]  4  以这棵树为范围,从左到右扫描,更新点数,x的+1, x+w的-1(超过矩形范围)  5  ans = 每次更新时所覆盖点数的最大值  6 */  7 #include <cstdio>  8 #include <algorithm>  9 #include <iostream>  10 #include <cstring>  11 #include <cmath>  12 #include <string>  13 #include <vector>  14 #include <queue>  15 #include <map>  16 #include <set>  17 #include <ctime>  18 #include <cstdlib>  19 using namespace std;  20  21 #define lson l, mid, rt << 1  22 #define rson mid + 1, r, rt << 1 | 1  23 typedef long long ll;  24  25 const int MAXN = 1e4 + 10; //n的范围  26 const int MAXM = 4e4 + 10; //x + 20000 范围  27 const int INF = 0x3f3f3f3f;  28 struct Node  29 {  30 int add, sum;  31 int l, r;  32 }node[MAXM << 2];  33 struct P  34 {  35 int x, y, c;  36 }p[MAXN * 2];  37  38 void push_up(int rt)  39 {  40 node[rt].sum = max (node[rt<<1].sum, node[rt<<1|1].sum);  41 }  42  43 void push_down(int rt)  44 {  45 if (node[rt].add)  46  {  47 node[rt<<1].add += node[rt].add;  48 node[rt<<1|1].add += node[rt].add;  49 node[rt<<1].sum += node[rt].add;  50 node[rt<<1|1].sum += node[rt].add;  51 node[rt].add = 0;  52  }  53 }  54  55 void build(int l, int r, int rt)  56 {  57 node[rt].add = 0; node[rt].sum = 0;  58 node[rt].l = l; node[rt].r = r;  59 if (l == r) return ;  60 int mid = (l + r) >> 1;  61  build (lson); build (rson);  62  63  push_up (rt);  64 }  65  66 void updata(int ql, int qr, int c, int rt)  67 {  68 if (ql == node[rt].l && node[rt].r == qr) {node[rt].sum += c; node[rt].add += c; return ;}  69  70  push_down (rt);  71  72 int mid = (node[rt].l + node[rt].r) >> 1;  73 if (qr <= mid) updata (ql, qr, c, rt << 1);  74 else if (ql > mid) updata (ql, qr, c, rt << 1 | 1);  75 else  76  {  77 updata (ql, mid, c, rt << 1);  78 updata (mid+1, qr, c, rt << 1 | 1);  79  }  80  81  push_up (rt);  82 }  83  84 bool cmp(P a, P b)  85 {  86 if (a.x == b.x) return a.c > b.c;  87 return a.x < b.x;  88 }  89  90 int main(void) //HDOJ 5091 Beam Cannon  91 {  92 //freopen ("B.in", "r", stdin);  93  94 int n, w, h;  95 while (scanf ("%d", &n) == 1)  96  {  97 if (n < 0) break;  98 scanf ("%d%d", &w, &h);  99 int cnt = 0; 100 for (int i=1; i<=n; ++i) 101  { 102 int x, y; 103 scanf ("%d%d", &x, &y); x += 20000; y += 20000; 104 p[++cnt].x = x; p[cnt].y = y; 105 p[cnt].c = 1; 106 p[++cnt].x = x + w; p[cnt].y = y; 107 p[cnt].c = -1; 108  } 109 sort (p+1, p+cnt+1, cmp); 110 111 build (0, 40000, 1); 112 113 int ans = 0; 114 for (int i=1; i<=cnt; ++i) 115  { 116 int y = p[i].y + h; if (y > 40000) y = 40000; 117 updata (p[i].y, y, p[i].c, 1); 118 ans = max (ans, node[1].sum); 119  } 120 121 printf ("%d\n", ans); 122  } 123 124 return 0; 125 }

 

你可能感兴趣的:(线段树)