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的最大值。
思路一下子就想出来了,可是怎么离散化想了好久。。
且放炸弹的区域不能含有士兵, 炸弹可以一次炸掉与它同一行同一列的所有士兵。 放一颗炸弹, 使得炸死的士兵最多。输出最大值。
思路:先不考虑离散化, 可以计算出水平方向和竖直方向上所有长度为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; }
相关文章推荐
- PHP中VC6、VC9、TS、NTS版本的区别与用法详解
- hdoj3664Permutation Counting【递推】
- hiho 14 并查集
- 数据库
- split 的 使用方法
- 2015.11.27初识java一集简单的java小程序
- CSS基础
- Web App开发入门
- nyoj 诡异的电梯【Ⅰ】 1070 (DP) 好题
- Linux压缩解压缩文章总结
- My way on Linux - 知识梳理计划
- 拉丁矩阵问题
- hdu 3466 Proud Merchants
- C语言端口扫描
- codeforces 412A Poster
- CodeForces 546C Soldier and Cards (队列)
- ViewPager
- objective - C 下字符串的处理方法
- Oracle例外处理
- PPT动画的若干问题