LOJ2392 JOISC2017 烟花棒 二分、贪心
先二分一个最大速度\(v\)。
分析移动的性质。很显然的事情是在火焰两边的所有人都会往火焰的方向以最快的速度运动,这样可以使当前位置更早获得火焰,同时当前拥有火焰的若干个人为了传递火焰自然也会以最快的速度移动。
接下来考虑某个没有火的人碰上了有火的人之后决策如何。假设有火的人\(A\)碰上了无火的人\(B\),如果\(A,B\)接下来要去的方向是一致的,那么肯定一起走直到\(A\)灭了再点燃\(B\);否则可以发现在碰上的瞬间点火和先\(AB\)一起走直到\(A\)无火时给\(B\)点火,这两种方案\(B\)能够点到火对应的相对距离范围是一致的。
所以我们可以认为\(AB\)相遇则一定会在一起跑,相当于给火焰增加了\(Tsec\)的燃烧时间,也就是说在任何时刻只会有最多一个位置有火。
那么我们实际需要做的决策就是在两个方向中选择一个方向让火往这边跑,将第一个相遇的位置加入火焰,再去做决策。不难发现在上述论述下,火焰向一边跑了之后到另一边所有人的相对距离不变,所以对于每一个人,如果火焰下一次选择它,那么消耗的时间是固定的,能够获得的时间也是固定的。我们把这两个值称为其权值,记为\((a_i,b_i)\)。
接下来的决策过程:从火焰的左边和右边找到第一个位置满足当火焰和这个位置相遇时时间相比开始增加。如果火焰可以往其中一个方向走到达这样的位置那么就走然后继续这个过程,否则肯定无解。
接下来到了走两边都一定让时间减少的部分,这里不能直接选择减的最少的位置走,因为这样的走法可能会影响决策集合从而导致无解。考虑一个常见的贪心Trick:我们已知过程结束时火焰的时间,那么我们倒着考虑,相当于把火焰左右的两个部分分别\(reverse\),\((a_i,b_i)\)交换然后做上述过程。这样不难证明从火焰左边的任何位置到最左端的位置一定能够获得正时间,右边同理。这样我们就可以通过这个问题是否有解得到整个问题是否有解了。
关于最后的Trick可以参考BZOJ3709
#include<bits/stdc++.h>
using namespace std;
int read(){
int a = 0; char c = getchar(); while(!isdigit(c)) c = getchar();
while(isdigit(c)){a = a * 10 + c - 48; c = getchar();} return a;
}
#define int long long
#define eps 1e-10
#define PII pair < int , int >
const int _ = 1e5 + 7;
int X[_] , N , K , T;
bool check(int sum , vector < PII > &A , vector < PII > &B){
int pos1 = 0 , pos2 = 0; if(sum < 0) return 0;
while(pos1 < A.size() || pos2 < B.size())
if(pos1 < A.size() && sum + A[pos1].first >= 0) sum += A[pos1++].second;
else if(pos2 < B.size() && sum + B[pos2].first >= 0) sum += B[pos2++].second;
else return 0;
return 1;
}
#define dis(a , b) ((X[a] - X[b]) / 2)
bool check1(int l1 , int r1 , int mid){
vector < PII > P , Q; int l = 0 , r = N + 1;
while(l < l1){
int pl = l , mn = 1e18;
while(pl != l1){
++pl; mn = min(mn , dis(pl , l + 1) - (pl - l) * T * mid);
if(dis(pl + 1 , l + 1) - (pl - l) * T * mid >= 0) break;
}
P.push_back(PII(mn , dis(pl + 1 , l + 1) - (pl - l) * T * mid)); l = pl;
}
while(r > r1){
int pr = r , mn = 1e18;
while(pr != r1){
--pr; mn = min(mn , dis(r - 1 , pr) - (r - pr) * T * mid);
if(dis(r - 1 , pr - 1) - (r - pr) * T * mid >= 0) break;
}
Q.push_back(PII(mn , dis(r - 1 , pr - 1) - (r - pr) * T * mid)); r = pr;
}
return check(T * mid * N - dis(N , 1) , P , Q);
}
bool check(int mid){
int l = K , r = K; vector < PII > P , Q;
while(l != 1){
int pl = l , mn = 1e18;
while(pl != 1){
mn = min(mn , (l - pl) * T * mid - dis(l , pl - 1));
--pl; if(dis(l , pl) <= (l - pl) * T * mid) break;
}
if(dis(l , pl) <= (l - pl) * T * mid) P.push_back(PII(mn , (l - pl) * T * mid - dis(l , pl)));
else break;
l = pl;
}
while(r != N){
int pr = r , mn = 1e18;
while(pr != N){
mn = min(mn , (pr - r) * T * mid - dis(pr + 1 , r));
++pr; if(dis(pr , r) <= (pr - r) * T * mid) break;
}
if(dis(pr , r) <= (pr - r) * T * mid) Q.push_back(PII(mn , (pr - r) * T * mid - dis(pr , r)));
else break;
r = pr;
}
return check(T * mid , P , Q) && check1(l - 1 , r + 1 , mid);
}
signed main(){
N = read(); K = read(); T = read() * 2; for(int i = 1 ; i <= N ; ++i) X[i] = read() * 2;
int L = 0 , R = 2e9 / T + 1;
while(L < R){
int mid = (L + R) >> 1;
check(mid) ? R = mid : L = mid + 1;
} cout << L; return 0;
}
LOJ2392 JOISC2017 烟花棒 二分、贪心的更多相关文章
- JOISC 2017 Day1 T3 烟花棒
JOISC 2017 Day1 T3 烟花棒 题意: 数轴上有\(N\)人在放烟花,一开始只有第\(K\)个人的烟花是点燃的,烟花燃烧的时间为\(T\)秒,求让所有人的烟花都可以点燃的速度的最小值 ...
- Codeforces Gym 100231B Intervals 线段树+二分+贪心
Intervals 题目连接: http://codeforces.com/gym/100231/attachments Description 给你n个区间,告诉你每个区间内都有ci个数 然后你需要 ...
- 2016-2017 ACM-ICPC CHINA-Final Ice Cream Tower 二分+贪心
/** 题目:2016-2017 ACM-ICPC CHINA-Final Ice Cream Tower 链接:http://codeforces.com/gym/101194 题意:给n个木块,堆 ...
- 【bzoj2097】[Usaco2010 Dec]Exercise 奶牛健美操 二分+贪心
题目描述 Farmer John为了保持奶牛们的健康,让可怜的奶牛们不停在牧场之间 的小路上奔跑.这些奶牛的路径集合可以被表示成一个点集和一些连接 两个顶点的双向路,使得每对点之间恰好有一条简单路径. ...
- Codeforces_732D_(二分贪心)
D. Exams time limit per test 1 second memory limit per test 256 megabytes input standard input outpu ...
- CF732D Exams 二分 贪心
思路:二分+贪心 提交次数:10次以上 错因:刚开始以为二分(边界,$+1or-1$)写错了,调了半天,后来才发现是$ck()$写错了.开始只判了最后是否小于零,而应该中间一旦小于零就$return\ ...
- $CF949D\ Curfew$ 二分/贪心
正解:二分/贪心 解题报告: 传送门$QwQ$ 首先这里是二分还是蛮显然的?考虑二分那个最大值,然后先保证一个老师是合法的再看另一个老师那里是否合法就成$QwQ$. 发现不太会搞这个合不合法的所以咕了 ...
- $bzoj2067\ szn$ 二分+贪心
正解:二分+贪心 解题报告: 传送门$QwQ$ 题目大意就说有一棵树,然后要用若干条线覆盖所有边且不能重叠.问最少要用几条线,在用线最少的前提下最长的线最短是多长. 昂首先最少用多少条线这个还是蛮$e ...
- leetcode1552题解【二分+贪心】
leetcode1552.两球之间的磁力 题目链接 算法 二分+贪心 时间复杂度O(nlogn + nlogm) 1.根据题意描述,我们需要将m个球放入到n个篮子中,根据题目中数据范围描述发现m &l ...
随机推荐
- Android源码分析(十五)----GPS冷启动实现原理分析
一:原理分析 主要sendExtraCommand方法中传递两个参数, 根据如下源码可以知道第一个参数传递delete_aiding_data,第二个参数传递null即可. @Override pub ...
- IDEA安装(2019.2版)
IDEA安装(2019.2版) 前段时间在公司实习接触过现下很火的 IDE,这里我根据搜集到的资料以及自己的实际操作整合了这篇博客,包括了安装和破解 IDEA,借此打开学习之旅. IntelliJ ...
- JMETER 使用断言
断言概念 断言就是在执行某个请求后,根据返回的结果,判断返回是否正确,如果不正确,则表示事务失败. 添加断言 启动流程时返回的数据是一个 json对象,结构为 {success:true,msg:&q ...
- canal中间件
简介: 基于数据库增量(模拟MySQL slave的交互协议)日志解析,提供增量数据订阅和消费(客户端与canal建立关系) 安装版本:1.1.0 git 环境需求: jdk1.7以上 mysql开启 ...
- 一文搞定PGA_LGA_BGA
概述 什么是LGA.PGA.BGA类型的封装?众所周知,CPU封装的类型主要为三种:LGA,PGA,BGA,其中LGA封装是最常见的,intel处理器都是采用这种类型的封装,而PGA封装则是AMD常用 ...
- Java 获取对象全部属性 包括 父类属性
今天由于业务需要,看一段数据库中的表转化成用户可以看懂的数据,也就是把一些字段比如Date用ms存的,转化为'yyyy-MM-dd'这种格式,但是由于字段太多,所以利用Java反射机制自带的BeanU ...
- CentOS7 最小安装 vmware 创建虚拟机 nmcli ip systemctl
镜像网站 一些开源软件的国内镜像源 站点版 (一).企业站 1.搜狐:http://mirrors.sohu.com/ 2.网易:http://mirrors.163.com/ 3.阿里云:http: ...
- NOIP 2008 立体图
洛谷 P1058 立体图 洛谷传送门 JDOJ 1541: [NOIP2008]立体图 T4 JDOJ传送门 题目描述 小渊是个聪明的孩子,他经常会给周围的小朋友们将写自己认为有趣的内容.最近,他准备 ...
- NOIP 2013 火柴排队
洛谷 P1966 火柴排队 洛谷传送门 JDOJ 2227: [NOIP2013]火柴排队 D1 T2 JDOJ传送门 Description 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高 ...
- mave常用指令
Maven常用命令有以下几种: 清理 maven clean 测试 maven test 编译 maven compile 打包 maven package 部署 maven install 第一个m ...