传送门


先二分一个最大速度\(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. ApiPost(中文版postman)如何发送一个随机数或者时间戳?

    什么是ApiPost内建变量:ApiPost提供了5个内建变量,如下: {{$guid}} //生成GUID {{$timestamp}} //当前时间戳 {{$microTimestamp}} // ...

  2. error: undefined reference to `vtable for

    出现如下错误: 解决办法 当类中加入Q_OBJECT,需要手动删除中间文件,再构建

  3. open_basedir restriction in effect

    vim /usr/local/nginx/conf/fastcgi.conf fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_ro ...

  4. vue用async、await实现同步请求

    以下是vue method的demo: loadTableData : async function() { var reses = await $.ajax({ type:'post', url:' ...

  5. Visual Studio调试到OpenCV源码中

    TL;DR VS2015下,build-farm/vs2015-x64/bin/Debug/目录,*.pdb文件,都拷贝到install/x64/vc14/bin目录,就可以调试进去opencv源码了 ...

  6. 网络编程(四)--基于udp协议的套接字、socketserver模块

    一.UDP协议(数据报协议) 1.何为udp协议 不可靠传输,”报头”部分一共只有8个字节,总长度不超过65,535字节,正好放进一个IP数据包. 以太网头 ip头                  ...

  7. K8S或docker的旁路容器注入排查

    使用这种排查技术的场景在于: 1,真正线上的POD,里面的排查工具很少.wget,curl,vi,telnet,ifconfig这些命令可能都没有. 2,排查的POD,什么工具都有,但与POD隔离,无 ...

  8. N种自动化测试框架(包含自动化和性能,总有一款适合你)

    不知不觉,分享的框架已经6个了(准确说应该是4个),仅仅是接口的. 这些框架都是最基础的框架,需要根据实际使用场景进行完善,大家就当练手实践吧. 不需要写代码的自动化框架 JMeter + Ant+ ...

  9. 排序算法-归并排序(Java)

    package com.rao.sort; import java.util.Arrays; /** * @author Srao * @className MergeSort * @date 201 ...

  10. Winform 弹框增加确定按钮并点击确定后进行下一步操作

    //审核完毕后调用打印 MessageBoxButtons messButton = MessageBoxButtons.OKCancel; DialogResult dr = MsgBox.Show ...