POJ 2482 Stars in Your Window 线段树

  如果按一般的思路来想,去求窗户能框住的星星,就很难想出来。

  如果换一个思路,找出每颗星星能被哪些窗户框住,这题就变得非常简单了。

  不妨以每个窗户的中心代表每个窗户,那么每颗星星所对应的窗户的范围即以其为中心的、W*H的矩形。把这些矩形的左边和右边,分别加上和减去其价值。而统计这些边只需要开一个线段树统计即可,用每次加边后得到的最大值更新答案。

  需要注意的是,计算这些边上两点的坐标时可能出现0.5的情况,为了避免,把原坐标*2即可。而且坐标过大,需要离散化。

  一开始打的时候,竟然,错了样例。仔细看了之后才发现窗户的长度为框住的点数+1,TAT

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <string>
  5 #include <algorithm>
  6 #include <iostream>
  7 #include <map>
  8 
  9 using namespace std;
 10 
 11 #define ls (rt<<1)
 12 #define rs ((rt<<1)+1)
 13 typedef long long LL;
 14 const int maxn = 20005;
 15 int n, m, W, H;
 16 struct Node
 17 {
 18     LL x, y1, y2, v;
 19     Node (LL x = 0, LL y1 = 0, LL y2 = 0, int v = 0):
 20         x(x), y1(y1), y2(y2), v(v) {}
 21     bool operator < (const Node &AI) const
 22     {
 23         if (x == AI.x)
 24             return v < AI.v;
 25         return x < AI.x;
 26     }
 27 }line[maxn*2];
 28 LL t[maxn];
 29 struct Tree
 30 {
 31     LL mv[maxn*4], delta[maxn*4];
 32     void Build(int rt, int l, int r)
 33     {
 34         delta[rt] = mv[rt] = 0;
 35         if (l == r)
 36             return ;
 37         int mid = (l+r)>>1;
 38         Build(ls, l, mid);
 39         Build(rs, mid+1, r);
 40     }
 41     void PushUp(int rt)
 42     {
 43         mv[rt] = max(mv[ls], mv[rs]);
 44     }
 45     void PushDown(int rt)
 46     {
 47         mv[ls] += delta[rt], mv[rs] += delta[rt];
 48         delta[ls] += delta[rt], delta[rs] += delta[rt];
 49         delta[rt] = 0;
 50     }
 51     void Update(int rt, int l, int r, int L, int R, int k)
 52     {
 53         if (L <= l && r <= R)
 54         {
 55             mv[rt] += k;
 56             delta[rt] += k;
 57             return ;
 58         }
 59         if (delta[rt] != 0)
 60             PushDown(rt);
 61         int mid = (l+r)>>1;
 62         if (L <= mid)
 63             Update(ls, l, mid, L, R, k);
 64         if (R > mid)
 65             Update(rs, mid+1, r, L, R, k);
 66         PushUp(rt);
 67     }
 68 }T;
 69 map <LL, int> num_y;
 70 
 71 int main()
 72 {
 73     while (~scanf("%d %d %d", &n, &W, &H))
 74     {
 75         W ++, H ++;
 76         m = 0;
 77         int Tcnt = 0;
 78         for (int i = 1; i <= n; ++i)
 79         {
 80             LL x, y, v;
 81             scanf("%lld %lld %lld", &x, &y, &v);
 82             line[++m] = Node(x*2-(W-1)+1, y*2-(H-1)+1, y*2+(H-1)-1, v);
 83             line[++m] = Node(x*2+(W-1), y*2-(H-1)+1, y*2+(H-1)-1, -v);
 84             t[++Tcnt] = y*2-(H-1)+1, t[++Tcnt] = y*2+(H-1)-1;
 85         }
 86         sort(t+1, t+Tcnt+1);
 87         int las_cnt = Tcnt;
 88         Tcnt = 0;
 89         for (int i = 1; i <= las_cnt; ++i)
 90             if (t[i] != t[i-1] || i == 1)
 91             {
 92                 t[++Tcnt] = t[i];
 93                 num_y[t[i]] = Tcnt;
 94             }
 95         sort(line+1, line+m+1);
 96         T.Build(1, 1, Tcnt);
 97         LL ans = 0;
 98         for (int i = 1; i <= m; ++i)
 99         {
100             T.Update(1, 1, Tcnt, num_y[line[i].y1], num_y[line[i].y2], line[i].v);
101             ans = max(ans, T.mv[1]);
102         }
103         printf("%lld\n", ans);
104     }
105     return 0;
106 }
View Code

 

posted @ 2017-02-08 20:58  Splay  阅读(250)  评论(0编辑  收藏  举报