题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=648&page=show_problem&problem=5153

In an infinite chess board, some pawns are placed on some cells.
You have a rectangular bomb that is W width and H height.
The bomb’s orientation is fixed, you can’t rotate it. The bomb
can only be placed on an entirely unoccupied area. The bomb
explodes both horizontally and vertically, killing all pawns that
are in the cross shape (see picture on the right).
Your mission is to choose the placement of the bomb, and
maximize the number of bombed pawns.
The picture corresponds to the first test case in the sample.
Input
The first line of the input gives the number of test cases, T. T
test cases follow. Each test case starts with a line containing N,
W, H, indicating number of pawns, width of the bomb, height of
the bomb, respectively.
N lines follow. Each line contains 2 integers: x, y, indicating there is a pawn on cell (x, y). No two
pawns are in the same cell.
Output
For each test case, output one line containing ‘Case #x: y’, where x is the test case number (stating
from 1) and y is the maximum number of bombed pawns.

题目大意:无穷大的地图上有n个兵,现给出一个W*H的炸弹(不可以旋转),一次能炸死它所在的行和列的所有小兵,不能放在小兵的上面。问:一次最多能干掉多少个小兵?

思路:最初的想法就是,枚举所有可以放炸弹的位置,看看哪个位置可以炸的小兵最多。如果用a[x, y]来表示炸弹放在以(x, y)为左下角的矩阵里,能炸多少小兵(不能放的时候为0)。那么显然结果就是a[x, y]的最大值。(作用:对拍)

然而这并不能AC。我们现在改成只考虑a数组的一个维度,让x一步一步往右移动,修改a数组。当我们在x位置的时候,用a[y]来表示,炸弹放在以(x, y)为左下角的矩阵里,能炸多少小兵。假设我们不考虑能不能放的问题,当x不断往右移动(不断+1)的时候,a数组并不会发生任何变化。我们可以另开一个数组cnt[],当我们遇到一个点(x0, y0)的时候,给cnt[y0-h+1..y0]都加上一个1,表示有一个点导致这个区间不能放入炸弹(同理当某个点离开区间[x..x+w-1]的时候,对应的区间都减去1)。那么我们在移动x的时候,要求的就是max{a[y] | cnt[y]=0}。

然而这还是不能AC。注意到在x往右移动的过程中,若没有点进出区间[x..x+w-1]的时候,cnt[]数组是不会发生变化的,这时,离散化x坐标的作用就发挥出来了。同时,y坐标也是可以离散化的,因为每次更改的区间都是可以提前预知的。

此时复杂度已经变成了O(n^2),当然还是不够的。注意到每次修改cnt[]数组都是区间修改,这里使用线段树优化,复杂度变为O(nlogn),可以AC。

此题细节多多,大家多想想。

PS:范围写的是w, h≥0,于是我加了一个assert,目前数据是没有w, h=0的情况的。如果rejudge RE了我就知道怎么回事啦!

代码(0.386S):

 #include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <tuple>
#include <cassert>
using namespace std;
typedef long long LL; const int MAXN = ;
const int MAXL = ;
const int MAXT = ; struct Node {
int x, y;
void read() {
scanf("%d%d", &x, &y);
}
} p[MAXN]; int val[MAXL]; vector<int> ytmp; int T, n, w, h; void inithash() {
ytmp.clear();
for(int i = ; i < n; ++i) {
ytmp.push_back(p[i].y - h + );
ytmp.push_back(p[i].y + );
}
sort(ytmp.begin(), ytmp.end());
ytmp.erase(unique(ytmp.begin(), ytmp.end()), ytmp.end());
} int yhash(int y) {
return lower_bound(ytmp.begin(), ytmp.end(), y) - ytmp.begin();
} void initval() {
memset(val, , ytmp.size() * sizeof(int));
for(int i = ; i < n; ++i) {
val[yhash(p[i].y - h + )]++;
val[yhash(p[i].y + )]--;
}
partial_sum(val, val + ytmp.size(), val);
} int root(int l, int r) {
return (l + r) | (l != r);
}
#define mid ((l + r) >> 1)
#define rt root(l, r)
#define ll root(l, mid)
#define rr root(mid + 1, r)
int ban[MAXT], maxt[MAXT]; void update(int l, int r) {
if(!ban[rt]) maxt[rt] = (l == r ? val[l] : max(maxt[ll], maxt[rr]));
else maxt[rt] = ;
} void build(int l, int r) {
if(l == r) {
maxt[rt] = val[l];
} else {
build(l, mid);
build(mid + , r);
update(l, r);
}
} void modify_ban(int l, int r, int a, int b, int val) {
if(a <= l && r <= b) {
ban[rt] += val;
} else {
if(a <= mid) modify_ban(l, mid, a, b, val);
if(mid < b) modify_ban(mid + , r, a, b, val);
}
update(l, r);
} int query() {
return maxt[root(, ytmp.size() - )];
} vector<int> allx;
vector<tuple<int, int, int> > xtmp;
#define gpos(t) get<0>(t)
#define gval(t) get<1>(t)
#define gy(t) get<2>(t) int solve() {
xtmp.clear();
for(int i = ; i < n; ++i) {
xtmp.push_back(make_tuple(p[i].x - w + , , p[i].y));
xtmp.push_back(make_tuple(p[i].x + , -, p[i].y));
}
sort(xtmp.begin(), xtmp.end()); allx.clear();
for(int i = ; i < n; ++i) {
allx.push_back(p[i].x - w + );
allx.push_back(p[i].x + );
}
sort(allx.begin(), allx.end());
allx.erase(unique(allx.begin(), allx.end()), allx.end()); int res = query(), cnt = ;
size_t i = ;
for(int x : allx) {
while(i < xtmp.size() && gpos(xtmp[i]) <= x) {
auto t = xtmp[i++];
modify_ban(, ytmp.size() - , yhash(gy(t) - h + ), yhash(gy(t) + ) - , gval(t));
cnt += gval(t);
}
res = max(res, query() + cnt);
}
return res;
} int main() {
scanf("%d", &T);
for(int t = ; t <= T; ++t) {
scanf("%d%d%d", &n, &w, &h);
assert(w > && h > );
for(int i = ; i < n; ++i)
p[i].read();
inithash();
initval();
build(, ytmp.size() - );
printf("Case #%d: %d\n", t, solve());
}
}

UVALive 7141 BombX(离散化+线段树)(2014 Asia Shanghai Regional Contest)的更多相关文章

  1. UVALive 7148 LRIP(树的分治+STL)(2014 Asia Shanghai Regional Contest)

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=6 ...

  2. UVALive 7138 The Matrix Revolutions(Matrix-Tree + 高斯消元)(2014 Asia Shanghai Regional Contest)

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=6 ...

  3. UVALive 7143 Room Assignment(组合数学+DP)(2014 Asia Shanghai Regional Contest)

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=6 ...

  4. UVALive 7147 World Cup(数学+贪心)(2014 Asia Shanghai Regional Contest)

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=6 ...

  5. UVALive 7139 Rotation(矩阵前缀和)(2014 Asia Shanghai Regional Contest)

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=6 ...

  6. UVALive 7146 Defeat the Enemy(贪心+STL)(2014 Asia Shanghai Regional Contest)

    Long long ago there is a strong tribe living on the earth. They always have wars and eonquer others. ...

  7. hdu5071 2014 Asia AnShan Regional Contest B Chat

    模拟题: add的时候出现过的则不再添加 close的时候会影响到top rotate(Prior.Choose)的时候会影响到top /*============================== ...

  8. 2014 Asia AnShan Regional Contest --- HDU 5073 Galaxy

    Galaxy Problem's Link:   http://acm.hdu.edu.cn/showproblem.php?pid=5073 Mean: 在一条数轴上,有n颗卫星,现在你可以改变k颗 ...

  9. dp --- 2014 Asia AnShan Regional Contest --- HDU 5074 Hatsune Miku

    Hatsune Miku Problem's Link:   http://acm.hdu.edu.cn/showproblem.php?pid=5074 Mean: 有m种音符(note),现在要从 ...

随机推荐

  1. Jquery事件:鼠标移入移出(mouseenter,mouseleave)

    前几天帮朋友做了一个单页面,其中有个效果就是鼠标移动到头像上变换头像样式,当鼠标移出时恢复头像样式.当时没多想,脑子就蹦出了mouseover,mouseout两个方法. 但是在编写页面的过程中,无论 ...

  2. 【资源】NOIP2013测试数据senior/junior 普及/提高 数据

    https://yunpan.cn/cRSepfcG4XX3V  访问密码 48e1 NOIP2013测试数据senior/junior 普及/提高 数据都在了

  3. C# CodeFirst(EF框架)代码优先创建数据库

    namespace WebEF.Model{ public class ModelContext:DbContext //继承DBcontext 来自EF框架 { public ModelContex ...

  4. java.math.RoundingMode 几个参数详解

    java.math.RoundingMode里面有几个参数搞得我有点晕,现以个人理解对其一一进行总结: 为了能更好理解,我们可以画一个XY轴 RoundingMode.CEILING:取右边最近的整数 ...

  5. java并发编程(十一)线程间的通信notify通知的遗漏

    notify通知的遗漏很容易理解,即threadA还没开始wait的时候,threadB已经notify了,这样,threadB通知是没有任何响应的,当threadB退出synchronized代码块 ...

  6. C++11 auto and decltype

    1.auto关键字 C++新标准引入auto关键词,此auto与之前C语言的auto意义已经不一样了. 这里的auto是修饰未知变量的类型,编译器会通过此变量的初始化自动推导变量的类型. 例如:aut ...

  7. 错误信息:attempt to create saveOrUpdate event with null entity

    错误信息:attempt to create saveOrUpdate event with null entity; 这个错误网上答案比较多,我也不多说了. 我遇到的问题是在前台传过来的参数是nul ...

  8. java核心技术第一卷

    sell窗口(dos窗口命令)中要注意大小写: 编译java文件需要加上扩展名,运行java.class时只要文件名java,不需要扩展名:

  9. 【5集iCore3_ADP演示视频】5-2 iCore3应用开发平台上电及注意事项

    iCore3双核心应用开发平台基于iCore3双核心板,包含ARM.FPGA.7寸液晶屏.双通道数字示波器.任意波发生器.电压表等模块,是一款专为电子爱好者设计的综合性电子学习系统. [视频简介]本视 ...

  10. completionService

    我们现在在Java中使用多线程通常不会直接用Thread对象了,而是会用到java.util.concurrent包下的ExecutorService类来初始化一个线程池供我们使用. 当我们使用Exe ...