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的最大值。
思路一下子就想出来了,可是怎么离散化想了好久。。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + ;
struct SegTree{
int seg[maxn << ], lazy[maxn << ];
void build(int l, int r, int pos, int val[]){
lazy[pos] = ;
if (l == r){
seg[pos] = val[l];
return;
}
int mid = (l + r) >> ;
build(l, mid, pos<<, val);
build(mid+, r, pos<<|, val);
seg[pos] = max(seg[pos<<], seg[pos<<|]);
}
void push_down(int pos){
if (lazy[pos]){
seg[pos<<] += lazy[pos];
seg[pos<<|] += lazy[pos];
lazy[pos<<] += lazy[pos];
lazy[pos<<|] += lazy[pos];
lazy[pos] = ;
}
}
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) >> ;
if (ua <= mid){
update(l, mid, pos<<, ua, ub, val);
}
if (ub > mid){
update(mid+, r, pos<<|, ua, ub, val);
}
seg[pos] = max(seg[pos<<], seg[pos<<|]);
}
}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, , sizeof prefixX);
memset(prefixY, , sizeof prefixY);
for (int i = ; i < maxn; i++){
vec1[i].clear();
vec2[i].clear();
}
}
int main(){
int T, cas = ;
scanf ("%d", &T);
while (T--){
int n, width, height;
scanf ("%d%d%d", &n, &width, &height);
tot1 = tot2 = ;
init();
for (int i = ; i < n; i++){
int x, y;
scanf ("%d%d", &x, &y);
pawX[i] = x, pawY[i] = y;
lshX[tot1++] = x;
lshX[tot1++] = x - width+;
lshY[tot2++] = y;
lshY[tot2++] = y-height+;
}
sort(lshX, lshX+tot1);
sort(lshY, lshY+tot2);
tot1 = unique(lshX, lshX+tot1) - lshX;
tot2 = unique(lshY, lshY+tot2) - lshY;
for (int i = ; i < n; i++){
int x1 = lower_bound(lshX, lshX+tot1, pawX[i]-width+) - lshX + ;
int x2 = lower_bound(lshX, lshX+tot1, pawX[i]) - lshX + ;
int y1 = lower_bound(lshY, lshY+tot2, pawY[i]-height+) - lshY + ;
int y2 = lower_bound(lshY, lshY+tot2, pawY[i]) - lshY + ;
prefixX[x1]++; prefixX[x2+]--;
prefixY[y1]++; prefixY[y2+]--;
vec1[y1].push_back(i);
vec2[y2].push_back(i);
}
int res = ;
for (int i = ; i <= tot1; i++){
prefixX[i] += prefixX[i-];
res = max(res, prefixX[i]); // 这里要特判一下
}
for (int i = ; i <= tot2; i++){
prefixY[i] += prefixY[i-];
res = max(res, prefixY[i]); // 这里要特判一下
}
tree.build(, tot1, , prefixX);
const int tenThousand = 1e5;
for (int i = ; i <= tot2; i++){
for (int j = ; j < vec1[i].size(); j++){
int idx = vec1[i][j];
int x = lower_bound(lshX, lshX+tot1, pawX[vec1[i][j]]) - lshX + ;
int y = lower_bound(lshX, lshX+tot1, pawX[vec1[i][j]]-width+) - lshX + ;
tree.update(, tot1, , y, x, -tenThousand);
}
int ret = tree.seg[];
if (ret > )
res = max(res, prefixY[i]+ret);
for (int j = ; j < vec2[i].size(); j++){
int x = lower_bound(lshX, lshX+tot1, pawX[vec2[i][j]]) - lshX + ;
int y = lower_bound(lshX, lshX+tot1, pawX[vec2[i][j]]-width+) - lshX + ;
tree.update(, tot1, , y, x, tenThousand);
}
}
printf("Case #%d: %d\n", cas++, res);
}
return ;
}
UVAlive7141 BombX 14年上海区域赛D题 线段树+离散化的更多相关文章
- UVALive 7148 LRIP 14年上海区域赛K题 树分治
题意 n个点组成一棵树, 带有点权. 求最长不降的路径的长度, 且路径上最大值最小值之差不超过D. 显然是树分治, 但是分治之后如何维护答案呢. 假设当前重心为g, 分别记录g出发不降路径的长度,以及 ...
- hdu 5475 模拟计算器乘除 (2015上海网赛H题 线段树)
给出有多少次操作 和MOD 初始值为1 操作1 y 表示乘上y操作2 y 表示除以第 y次操作乘的那个数 线段树的叶子结点i 表示 第i次操作乘的数 将1替换成y遇到操作2 就把第i个结点的值 替换成 ...
- ACM 2015年上海区域赛A题 HDU 5572An Easy Physics Problem
题意: 光滑平面,一个刚性小球,一个固定的刚性圆柱体 ,给定圆柱体圆心坐标,半径 ,小球起点坐标,起始运动方向(向量) ,终点坐标 ,问能否到达终点,小球运动中如果碰到圆柱体会反射. 学到了向量模板, ...
- UVALive 8519 Arrangement for Contests 2017西安区域赛H 贪心+线段树优化
题意 等价于给一个数列,每次对一个长度为$K$的连续区间减一 为最多操作多少次 题解: 看样例猜的贪心,10分钟敲了个线段树就交了... 从1开始,找$[i,i+K]$区间的最小值,然后区间减去最小值 ...
- hdu 4031 2011成都赛区网络赛A题 线段树 ***
就是不知道时间该怎么处理,想了好久,看了别人的题解发现原来是暴力,暴力也很巧妙啊,想不出来的那种 -_-! #include<cstdio> #include<iostream&g ...
- HDU - 6521 Party (SYSU校赛K题)(线段树)
题目链接 题意:n个人排成一列,一开始他们互不认识,每次选[l,r]上的人开party,使他们互相认识,求出每次party之后新互相认识的人的对数. 思路:把“互相认识”变成单向连边,只考虑左边的人对 ...
- 2019 ICPC 上海区域赛总结
2019上海区域赛现场赛总结 补题情况(以下通过率为牛客提交): 题号 标题 已通过代码 通过率 我的状态 A Mr. Panda and Dominoes 点击查看 5/29 未通过 B Prefi ...
- HDU-5532//2015ACM/ICPC亚洲区长春站-重现赛-F - Almost Sorted Array/,哈哈,水一把区域赛的题~~
F - Almost Sorted Array Time Limit:2000MS Memory Limit:262144KB 64bit IO Format:%I64d & ...
- hdu5080:几何+polya计数(鞍山区域赛K题)
/* 鞍山区域赛的K题..当时比赛都没来得及看(反正看了也不会) 学了polya定理之后就赶紧跑来补这个题.. 由于几何比较烂写了又丑又长的代码,还debug了很久.. 比较感动的是竟然1Y了.. * ...
随机推荐
- Oracle11g服务及实例
1Orcl服务说明 1) Oracle ORCL VSS Writer Service:Oracle卷映射拷贝写入服务,VSS(Volume Shadow Copy Service)能够让存储基础设备 ...
- OC基础-day04
#pragma mark - Day04_01_匿名对象 1. 如果函数有返回值 我们可以不使用变量接收返回值. 而是直接将函数写在要使用其返回值的地方. 2. 正常情况下.我创建对象. 是使用了1 ...
- CSS 边框
CSS 边框属性 CSS边框属性允许你指定一个元素边框的样式和颜色. 边框样式 边框样式属性指定要显示什么样的边界. border-style属性用来定义边框的样式 border-style 值: ...
- wireshark添加用户执行
默认情况下,访问网络端口需要root权限,而wireshark的只是/usr/share/dumpcap的一个UI,/usr/share/dumpcap需要root权限,所以没法non-root用户无 ...
- JS异步阻塞的迷思
还是百度前端技术学院的“任务十九”可视化排序算法的题,在写出快速排序算法之后,要求用动画的形式把这个排序过程呈现出来.排序过程在CPU里不过是瞬间的事,但要转换成“缓慢的”动画效果给人类看,就不得不把 ...
- linux创建守护进程
守护进程deamon 是一个后台进程,无需用户输入就能运行,用来在系统后台提供某种服务. 常见的守护进程有Wbe服务器.邮件服务器以及数据库服务器等等.守护进程不能控制终端,所以任何的输入和输出都需要 ...
- pc110301QWERTYU
水题一道,SOLVED只是次数的问题.map一下,就是很easy啦. #include<iostream> #include<cstdio> #include<cstri ...
- ARM开发板系统移植-----kernel的编译
前面一篇文章http://www.cnblogs.com/linzizhang/p/4817336.html介绍了开发板上系统软件的第一部分--bootloader的编译方法. 背景:把bootloa ...
- jquery 三种开始写法
在 jquery 代码中使用 $(document).ready()时,位于其中的所有代码都会在 DOM 加载后立即执行 第一种(推荐)$(document).ready(function(){ ...
- 关于webapp的一个webframe问题
最近重启ios webapp的项目,将之前的框架拿过来发现出现了错误,错误出现在写JSAlart控件的WebFrame上,xcode会报WebFrame是未定义的错误.由于之前使用的是ios5的 sd ...