传送门


先二分一个最大速度\(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 烟花棒 二分、贪心的更多相关文章

  1. JOISC 2017 Day1 T3 烟花棒

    JOISC 2017 Day1 T3 烟花棒 题意: ​ 数轴上有\(N\)人在放烟花,一开始只有第\(K\)个人的烟花是点燃的,烟花燃烧的时间为\(T\)秒,求让所有人的烟花都可以点燃的速度的最小值 ...

  2. Codeforces Gym 100231B Intervals 线段树+二分+贪心

    Intervals 题目连接: http://codeforces.com/gym/100231/attachments Description 给你n个区间,告诉你每个区间内都有ci个数 然后你需要 ...

  3. 2016-2017 ACM-ICPC CHINA-Final Ice Cream Tower 二分+贪心

    /** 题目:2016-2017 ACM-ICPC CHINA-Final Ice Cream Tower 链接:http://codeforces.com/gym/101194 题意:给n个木块,堆 ...

  4. 【bzoj2097】[Usaco2010 Dec]Exercise 奶牛健美操 二分+贪心

    题目描述 Farmer John为了保持奶牛们的健康,让可怜的奶牛们不停在牧场之间 的小路上奔跑.这些奶牛的路径集合可以被表示成一个点集和一些连接 两个顶点的双向路,使得每对点之间恰好有一条简单路径. ...

  5. Codeforces_732D_(二分贪心)

    D. Exams time limit per test 1 second memory limit per test 256 megabytes input standard input outpu ...

  6. CF732D Exams 二分 贪心

    思路:二分+贪心 提交次数:10次以上 错因:刚开始以为二分(边界,$+1or-1$)写错了,调了半天,后来才发现是$ck()$写错了.开始只判了最后是否小于零,而应该中间一旦小于零就$return\ ...

  7. $CF949D\ Curfew$ 二分/贪心

    正解:二分/贪心 解题报告: 传送门$QwQ$ 首先这里是二分还是蛮显然的?考虑二分那个最大值,然后先保证一个老师是合法的再看另一个老师那里是否合法就成$QwQ$. 发现不太会搞这个合不合法的所以咕了 ...

  8. $bzoj2067\ szn$ 二分+贪心

    正解:二分+贪心 解题报告: 传送门$QwQ$ 题目大意就说有一棵树,然后要用若干条线覆盖所有边且不能重叠.问最少要用几条线,在用线最少的前提下最长的线最短是多长. 昂首先最少用多少条线这个还是蛮$e ...

  9. leetcode1552题解【二分+贪心】

    leetcode1552.两球之间的磁力 题目链接 算法 二分+贪心 时间复杂度O(nlogn + nlogm) 1.根据题意描述,我们需要将m个球放入到n个篮子中,根据题目中数据范围描述发现m &l ...

随机推荐

  1. Date工具类

    总结了下项目中常用的时间转化方法,目前就这么点啦,以后再慢慢添加,先储备起来,免得丢啦. package com.example.keranbin.testdemo; import android.u ...

  2. 各主流摄像头的rtsp地址格式

    海康威视rtsp://[username]:[password]@[ip]:[port]/[codec]/[channel]/[subtype]/av_stream说明:username: 用户名.例 ...

  3. windows系统DOC命令启动或停止服务

    -- 启动服务 -- net start Mysql -- 停止服务 -- net stop Mysql-- 说明:MysqL没有大小写区分.可以直接小写mysql. -- 启动报错(net star ...

  4. hdu1801 01翻转 贪心

    题目描述: 对于给出的一个n*m的矩形,它由1和0构成,现在给你一个r*c的矩形空间可以选择,且可以选择无数次(被选中的范围内01翻转),要求问将这个01矩阵全部变成0的最少需要翻多少次,且如果无法实 ...

  5. 编译3516cv500 osdrv失败解决

    configure: WARNING: cannot find uuid library required for mkfs.ubifsconfigure: mtd-utils can optiona ...

  6. 用 tomcat 部署 Jenkins

    在tomcat 下面部署 Jenkins 版本 tomcat (7.0.94) +  jdk (7) + jenkins (2.46.3) 前两次没有部署成功,应该是 jdk 版本的问题, 如果不成功 ...

  7. Install PDFtk on Ubuntu

    https://linuxhint.com/install_pdftk_ubuntu/ PDF is an integral part of our everyday life. It’s a doc ...

  8. 安装Vyos

      Vyos是一个开源的网络操作系统,基于Debian,相对于ROS需要购买license,Vyos就更加开放的多. 下载Vyos wget http://vyos.hecint.com/iso/re ...

  9. zzulioj - 2617 体检

    题目链接: http://acm.zzuli.edu.cn/problem.php?id=2617 题目描述: VX玩了这么多游戏以后,感觉自己身体素质和智商都有所下降,所以决定去医院体检一下.已知V ...

  10. 说几条JavaScript的基本规范

    1.不要在同一行声明多个变量 2.使用===或!==来比较 3.使用字面量的方式来创建对象.数组,替代new Array这种形式 4.不要使用全局函数 5.switch语句必须要带default分支 ...