您的位置:首页 > 其它

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

2015-11-27 21:05 429 查看
题意:一个无限大的棋盘, 有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的最大值。

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

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;
struct SegTree{
int seg[maxn << 2], lazy[maxn << 2];
void build(int l, int r, int pos, int val[]){
lazy[pos] = 0;
if (l  == r){
seg[pos] = val[l];
return;
}
int mid = (l + r) >> 1;
build(l, mid, pos<<1, val);
build(mid+1, r, pos<<1|1, val);
seg[pos] = max(seg[pos<<1], seg[pos<<1|1]);
}
void push_down(int pos){
if (lazy[pos]){
seg[pos<<1] += lazy[pos];
seg[pos<<1|1] += lazy[pos];
lazy[pos<<1] += lazy[pos];
lazy[pos<<1|1] += lazy[pos];
lazy[pos] = 0;
}
}
void update (int l, int r, int pos, int ua, int ub, int val){
if (ua > ub){
return;
}
if (ua <= l && ub >= r){
seg[pos] += val;
lazy[pos] += val;
return;
}
push_down(pos);
int mid = (l + r) >> 1;
if (ua <= mid){
update(l, mid, pos<<1, ua, ub, val);
}
if (ub > mid){
update(mid+1, r, pos<<1|1, ua, ub, val);
}
seg[pos] = max(seg[pos<<1], seg[pos<<1|1]);
}
}tree;
int pawX[maxn], pawY[maxn];
int lshX[maxn], lshY[maxn], tot1, tot2;
int prefixX[maxn], prefixY[maxn], valX[maxn], valY[maxn];
vector <int> vec1[maxn], vec2[maxn];
void init(){
memset(prefixX, 0, sizeof prefixX);
memset(prefixY, 0, sizeof prefixY);
for (int i = 0; i < maxn; i++){
vec1[i].clear();
vec2[i].clear();
}
}
int main(){
int T, cas = 1;
scanf ("%d", &T);
while (T--){
int n, width, height;
scanf ("%d%d%d", &n, &width, &height);
tot1 = tot2 = 0;
init();
for (int i = 0; i < n; i++){
int x, y;
scanf ("%d%d", &x, &y);
pawX[i] = x, pawY[i] = y;
lshX[tot1++] = x;
lshX[tot1++] = x - width+1;
lshY[tot2++] = y;
lshY[tot2++] = y-height+1;
}
sort(lshX, lshX+tot1);
sort(lshY, lshY+tot2);
tot1 = unique(lshX, lshX+tot1) - lshX;
tot2 = unique(lshY, lshY+tot2) - lshY;
for (int i = 0; i < n; i++){
int x1 = lower_bound(lshX, lshX+tot1, pawX[i]-width+1) - lshX + 1;
int x2 = lower_bound(lshX, lshX+tot1, pawX[i]) - lshX + 1;
int y1 = lower_bound(lshY, lshY+tot2, pawY[i]-height+1) - lshY + 1;
int y2 = lower_bound(lshY, lshY+tot2, pawY[i]) - lshY + 1;
prefixX[x1]++; prefixX[x2+1]--;
prefixY[y1]++; prefixY[y2+1]--;
vec1[y1].push_back(i);
vec2[y2].push_back(i);
}
int res = 0;
for (int i = 1; i <= tot1; i++){
prefixX[i] += prefixX[i-1];
res = max(res, prefixX[i]);           // 这里要特判一下
}
for (int i = 1; i <= tot2; i++){
prefixY[i] += prefixY[i-1];
res = max(res, prefixY[i]);           // 这里要特判一下
}
tree.build(1, tot1, 1, prefixX);
const int tenThousand = 1e5;
for (int i = 1; i <= tot2; i++){
for (int j = 0; j < vec1[i].size(); j++){
int idx = vec1[i][j];
int x = lower_bound(lshX, lshX+tot1, pawX[vec1[i][j]]) - lshX + 1;
int y = lower_bound(lshX, lshX+tot1, pawX[vec1[i][j]]-width+1) - lshX + 1;
tree.update(1, tot1, 1, y, x, -tenThousand);
}
int ret  = tree.seg[1];
if (ret > 0)
res = max(res, prefixY[i]+ret);
for (int j = 0; j < vec2[i].size(); j++){
int x = lower_bound(lshX, lshX+tot1, pawX[vec2[i][j]]) - lshX + 1;
int y = lower_bound(lshX, lshX+tot1, pawX[vec2[i][j]]-width+1) - lshX + 1;
tree.update(1, tot1, 1, y, x,  tenThousand);
}
}
printf("Case #%d: %d\n", cas++, res);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: