UVAlive7141 BombX 14年上海区域赛D题 线段树+离散化

题意:一个无限大的棋盘, 有n个小兵, 给出了n个兵的坐标, 现在有一个长为width 高为height的炸弹放在棋盘上, 炸弹只能上下左右平移, 不能旋转。

且放炸弹的区域不能含有士兵, 炸弹可以一次炸掉与它同一行同一列的所有士兵。 放一颗炸弹, 使得炸死的士兵最多。输出最大值。

思路:先不考虑离散化, 可以计算出水平方向和竖直方向上所有长度为width和height区间内士兵的个数, 得到一个数组prefixX, prefixY。

然后一次遍历prefixY数组, 假设区间[i, i+height-1]对应prefixY[i], 而且[i, i+height-1]内所有士兵的x坐标对应的prefixX都减去一个大于n的数字MAX(这样保证炸弹不会放在士兵上),这个时候求prefixX上的一个最大值max再加上prefixY[i]就可以更新答案result了, 如果max是一个负数那么说明当前这个区间不能放炸弹。 之后再把第i行的所有士兵的x坐标对应的prefixX都加上MAX。 这样一次下去就可以了。线段树区间操作。

还有一个需要特判的地方是 上面并没有找到一个可以放炸弹的地方。 这个时候答案就是prefixX和prefixY的最大值。

思路一下子就想出来了,可是怎么离散化想了好久。。

 

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 const int maxn = 2e5 + 5;
  4 struct SegTree{
  5     int seg[maxn << 2], lazy[maxn << 2];
  6     void build(int l, int r, int pos, int val[]){
  7         lazy[pos] = 0;
  8         if (l  == r){
  9             seg[pos] = val[l];
 10             return;
 11         }
 12         int mid = (l + r) >> 1;
 13         build(l, mid, pos<<1, val);
 14         build(mid+1, r, pos<<1|1, val);
 15         seg[pos] = max(seg[pos<<1], seg[pos<<1|1]);
 16     }
 17     void push_down(int pos){
 18         if (lazy[pos]){
 19             seg[pos<<1] += lazy[pos];
 20             seg[pos<<1|1] += lazy[pos];
 21             lazy[pos<<1] += lazy[pos];
 22             lazy[pos<<1|1] += lazy[pos];
 23             lazy[pos] = 0;
 24         }
 25     }
 26     void update (int l, int r, int pos, int ua, int ub, int val){
 27         if (ua > ub){
 28             return;
 29         }
 30         if (ua <= l && ub >= r){
 31             seg[pos] += val;
 32             lazy[pos] += val;
 33             return;
 34         }
 35         push_down(pos);
 36         int mid = (l + r) >> 1;
 37         if (ua <= mid){
 38             update(l, mid, pos<<1, ua, ub, val);
 39         }
 40         if (ub > mid){
 41             update(mid+1, r, pos<<1|1, ua, ub, val);
 42         }
 43         seg[pos] = max(seg[pos<<1], seg[pos<<1|1]);
 44     }
 45 }tree;
 46 int pawX[maxn], pawY[maxn];
 47 int lshX[maxn], lshY[maxn], tot1, tot2;
 48 int prefixX[maxn], prefixY[maxn], valX[maxn], valY[maxn];
 49 vector <int> vec1[maxn], vec2[maxn];
 50 void init(){
 51     memset(prefixX, 0, sizeof prefixX);
 52     memset(prefixY, 0, sizeof prefixY);
 53     for (int i = 0; i < maxn; i++){
 54         vec1[i].clear();
 55         vec2[i].clear();
 56     }
 57 }
 58 int main(){
 59     int T, cas = 1;
 60     scanf ("%d", &T);
 61     while (T--){
 62         int n, width, height;
 63         scanf ("%d%d%d", &n, &width, &height);
 64         tot1 = tot2 = 0;
 65         init();
 66         for (int i = 0; i < n; i++){
 67             int x, y;
 68             scanf ("%d%d", &x, &y);
 69             pawX[i] = x, pawY[i] = y;
 70             lshX[tot1++] = x;
 71             lshX[tot1++] = x - width+1;
 72             lshY[tot2++] = y;
 73             lshY[tot2++] = y-height+1;
 74         }
 75         sort(lshX, lshX+tot1);
 76         sort(lshY, lshY+tot2);
 77         tot1 = unique(lshX, lshX+tot1) - lshX;
 78         tot2 = unique(lshY, lshY+tot2) - lshY;
 79         for (int i = 0; i < n; i++){
 80             int x1 = lower_bound(lshX, lshX+tot1, pawX[i]-width+1) - lshX + 1;
 81             int x2 = lower_bound(lshX, lshX+tot1, pawX[i]) - lshX + 1;
 82             int y1 = lower_bound(lshY, lshY+tot2, pawY[i]-height+1) - lshY + 1;
 83             int y2 = lower_bound(lshY, lshY+tot2, pawY[i]) - lshY + 1;
 84             prefixX[x1]++; prefixX[x2+1]--;
 85             prefixY[y1]++; prefixY[y2+1]--;
 86             vec1[y1].push_back(i);
 87             vec2[y2].push_back(i);
 88         }
 89         int res = 0;
 90         for (int i = 1; i <= tot1; i++){
 91             prefixX[i] += prefixX[i-1];
 92             res = max(res, prefixX[i]);           // 这里要特判一下
 93         }
 94         for (int i = 1; i <= tot2; i++){
 95             prefixY[i] += prefixY[i-1];
 96             res = max(res, prefixY[i]);           // 这里要特判一下
 97         }
 98         tree.build(1, tot1, 1, prefixX);
 99         const int tenThousand = 1e5;
100         for (int i = 1; i <= tot2; i++){
101             for (int j = 0; j < vec1[i].size(); j++){
102                 int idx = vec1[i][j];
103                 int x = lower_bound(lshX, lshX+tot1, pawX[vec1[i][j]]) - lshX + 1;
104                 int y = lower_bound(lshX, lshX+tot1, pawX[vec1[i][j]]-width+1) - lshX + 1;
105                 tree.update(1, tot1, 1, y, x, -tenThousand);
106             }
107             int ret  = tree.seg[1];
108             if (ret > 0)
109                 res = max(res, prefixY[i]+ret);
110             for (int j = 0; j < vec2[i].size(); j++){
111                 int x = lower_bound(lshX, lshX+tot1, pawX[vec2[i][j]]) - lshX + 1;
112                 int y = lower_bound(lshX, lshX+tot1, pawX[vec2[i][j]]-width+1) - lshX + 1;
113                 tree.update(1, tot1, 1, y, x,  tenThousand);
114             }
115         }
116         printf("Case #%d: %d\n", cas++, res);
117     }
118     return 0;
119 }

 

posted @ 2015-11-27 21:05  PlasticSpirit  阅读(406)  评论(0编辑  收藏  举报