AGC012 - E: Camel and Oases
题意简述
沙漠中有n(n≤2×105)个排成一条直线的绿洲,一头储水量为V(V≤2×105)的骆驼。
骆驼有两个操作:
- 走到距离在V以内的一个绿洲。
- 飞到任意一个绿洲,但V减少一半。V=0时不能飞。
问骆驼依次从每个绿洲出发,能否一次性遍历所有绿洲。
分析
首先预处理出 V=V0 时哪些绿洲之间是可以随便走的,对于每个V0扫一遍即可。时间复杂度为O(nlog2V)。
每飞一次相当于下一层。题目转化成钦定第一条线段,然后从每一层选一条线段,问能否覆盖整个区间。
万万没想到,这道题居然是状压DP!!!
s中的后起第i位为1表示从第i层选出了一条线段。
f1[s]表示状态s时从1起向右最远能延伸到哪,f2[s]表示状态s时从n起向左最远能延伸到哪。
f1[s]=max(f1[s],upFind(f1[s0]))
f2[s]=min(f2[s],lowFind(f2[s0]−1))
意义是从s0加上一条线段能延伸到哪。这个转移方程和我的写法有关,具体看代码。
时间复杂度O(log2V⋅log2n⋅2log2V+1)=O(Vlog2nlog2V)
检查答案时,对于第一层的每一条线段,寻找是否存在s,使得f1[s],f2[U−s−1]和该线段覆盖整个区间。表示用状态s这些线段尽可能扩展左半部分,用剩下的线段(不包括第一层)尽可能扩展右半部分,再加上第一层的这条线段。
最大时间复杂度O(n⋅2log2V)=O(nV),GG ╮(╯﹏╰)╭
但实际上,第一层的线段条数是不能超过log2V+1的。因为飞log2V+1次后V0=0,并且下一层的条数比上一层只多不少,要是第一层就超过log2V+1那么不可能遍历所有绿洲。
所以最大时间复杂度为O(Vlog2V)。
总时间复杂度最大为O(nlog2V+Vlog2nlog2V)。
实现
a[i][j]记录第i层的第j条线段的右端点。特别地,a[i][0]记录第i层线段的条数。
upFind(x)找出第一个严格大于x的右端点。这个右端点所在的区间一定能延伸当前的f1。
lowFind(x−1)找出第一个严格小于x-1的右端点。这个右端点的下一个区间一定能延伸当前的f2。如果写lowFind(x),要是找到x-1的话,说明有一段以x-1为右端点的区间以及一段以x为左端点的区间。这时候明明可以加入前者,实际上却加入了后者,导致问题。
代码
//Camel and Oases
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long lint;
int const N=2e5+10;
int const S=1<<19;
int n,V;
lint d[N];
int logV,a[25][N];
int U,f1[S],f2[S];
int upFind(int a[],int x)
{
int L=1,R=a[0];
while(L<R-1)
{
int mid=(L+R)>>1;
if(a[mid]<=x) L=mid+1;
if(a[mid]>x) R=mid;
}
if(a[L]>x) return a[L];
else return a[R];
}
int lowFind(int a[],int x)
{
int L=1,R=a[0];
while(L<R-1)
{
int mid=(L+R)>>1;
if(a[mid]<x) L=mid;
if(a[mid]>=x) R=mid-1;
}
if(a[R]<x) return a[R]+1;
else return a[L]+1;
}
int main()
{
scanf("%d%d",&n,&V);
logV=0;
while((1<<logV)<=V) logV++;
logV++;
for(int i=1;i<=n;i++) scanf("%lld",&d[i]),d[i-1]=d[i]-d[i-1];
d[n]=0;
for(int i=1;i<=logV;i++)
{
a[i][0]=1;
for(int j=1;j<=n;j++)
{
a[i][a[i][0]]=j;
if(d[j]>(V>>(i-1))) a[i][0]++;
}
}
if(a[1][0]>logV)
{
for(int i=1;i<=n;i++) printf("Impossible\n");
return 0;
}
U=(1<<logV)-1;
for(int s=0;s<=U;s++) f1[s]=0,f2[s]=n+1;
for(int s=0;s<=U;s+=2)
for(int i=2;i<=logV;i++)
{
int s0=1<<(i-1);
if(s&s0) continue;
f1[s|s0]=max(f1[s|s0],upFind(a[i],f1[s]));
f2[s|s0]=min(f2[s|s0],lowFind(a[i],f2[s]-1));
}
for(int i=1;i<=a[1][0];i++)
{
bool f=false;
int fr=a[1][i-1]+1,to=a[1][i];
if(i==1) fr=1;
for(int s=0;s<=U&&!f;s+=2)
if(fr<=f1[s]+1 && f2[U-s-1]-1<=to) f=true;
if(f) for(int j=fr;j<=to;j++) printf("Possible\n");
else for(int j=fr;j<=to;j++) printf("Impossible\n");
}
return 0;
}
注意
- 因为最多飞log2V+1次,所以全集状态U=2log2V+1−1,体现在题目中为219,而不是218。
- a[i][0]做他用,有些地方写的可能会麻烦一些。
AGC012 - E: Camel and Oases的更多相关文章
- 【AtCoder】【模拟】【模型转化】Camel and Oases(AGC012)
题意: 有一个骆驼,n个绿洲遍布在数轴上,第i个绿洲的坐标为x[i],保证x[i]单增.骆驼的驼峰有体积初始值V.当驼峰的体积变为v的时候,驼峰中至多只能够存储v L的水.骆驼希望走完所有的绿洲,并且 ...
- 【agc012E】Camel and Oases
Portal --> agc012 Description 有一排点,两点间有一定距离,初始的时候有一个行走值\(v\),如果说两点间距离不超过\(v\),那么可以在这两点间自由行走,如果当前\ ...
- 【AGC012E】 Camel and Oases ST表+状压dp
题目大意:一排点,两点间有距离. 初始你有一个行走值$v$,如果相邻两点距离不超过$v$你可以自由在这两点行走. 当$v$大于$0$时,你可以选择某一时刻突然飞到任意点,这样做后$v$会减半(下取整) ...
- [AGC012E]Camel and Oases
题意:有$n$个数轴上的绿洲,给定它们的坐标,有一只骆驼想要访问所有绿洲,当它的驼峰容量为$V$时,它可以走到和当前绿洲距离$\leq V$的绿洲,并可以继续走,它也可以用一次跳跃到达任意一个绿洲,只 ...
- Agc012_E Camel and Oases
传送门 题目大意 坐标轴上有$n$个坐标,第$i$个坐标是$x_i$,初始你有一个容量$V$,当两个给定的坐标距离不超过$V$时,你可以从一个坐标到达另一个坐标,同时你还可以令$V=\lfloor \ ...
- 【AtCoder】AGC012
AGC012 A - AtCoder Group Contest 从最后开始间隔着取就行 #include <bits/stdc++.h> #define fi first #define ...
- AtCoder Grand Contest 012
AtCoder Grand Contest 012 A - AtCoder Group Contest 翻译 有\(3n\)个人,每一个人有一个强大值(看我的假翻译),每三个人可以分成一组,一组的强大 ...
- A♂G&C012
A♂G&C012 A AtCoder Group Contest 从大到小sort后输出\(a_2+a_4+a_6+\ldots a_{2n}\) 好♂啊,只会背结论/kk B Splatte ...
- Camel运行原理分析
Camel运行原理分析 以一个简单的例子说明一下camel的运行原理,例子本身很简单,目的就是将一个目录下的文件搬运到另一个文件夹,处理器只是将文件(限于文本文件)的内容打印到控制台,首先代码如下: ...
随机推荐
- js promise看这篇就够了
一.背景 大家都知道nodejs很快,为什么会这么快呢,原因就是node采用异步回调的方式来处理需要等待的事件,使得代码会继续往下执行不用在某个地方等待着.但是也有一个不好的地方,当我们有很多回调的时 ...
- unicode文件处理(如果是ANSI编码就不需要了)
1.unicode文件的打开必须用rb模式. 3.wchar_t str[100] = { 0 }; 这个占200个字节. 2.宽字符对应的处理 fgetc fgetwc fputc fputwc f ...
- 关于异步IO与同步IO的写操作区别
最近这两天都在看IO相关的知识点.一开始太凌乱,太杂,不过终于整理清楚了.觉得杂乱是因为一开始以为异步IO等于非阻塞IO,这完全是两个概念, LINUX下的异步IO有两类,一类为glibc AIO,这 ...
- 12、SEO工程师指南 - 软件项目角色指南系列文章
第11章 SEO工程师 SEO工程师是一个比较新兴的职位,在实际的项目管理过程中,SEO工程师的地位相对靠后,只有在项目试运行以及运营期间才能体现出SEO工程师的作用.在项目完成之后, ...
- verilog实验2:基于FPGA的59秒计时器设计
一.实验任务 利用四个数码管显示59秒计时器. 二.代码实现 将开发板的48M晶振分频出1M,然后计数器累加,将计数器结果显示在数码管上.低位逢十进一,第二位逢五进一,依次构成59秒计时器. 部分代码 ...
- [Sdoi2017]数字表格 [莫比乌斯反演]
[Sdoi2017]数字表格 题意:求 \[ \prod_{i=1}^n \prod_{j=1}^m f[(i,j)] \] 考场60分 其实多推一步就推倒了... 因为是乘,我们可以放到幂上 \[ ...
- BZOJ 1593: [Usaco2008 Feb]Hotel 旅馆 [线段树]
传送门 题意: 操作1:找长为$len$的空区间并填满,没有输出$0$ 操作2:将$[l,r]$之间的区间置空 我真是太弱了这种线段树还写了一个半小时,中间为了查错手动模拟了$30min$线段树操作, ...
- [测试]java IO写入文件效率——几种方法比较
各类写入方法 /** *1 按字节写入 FileOutputStream * * @param count 写入循环次数 * @param str 写入字符串 */ public void outpu ...
- Orleans入门例子
Orleans入门例子 这是Orleans系列文章中的一篇.首篇文章在此 一.铺垫. 虽然是个入门例子,还是需要一些铺垫. Orleans的最小完全体,应该分为2个部分.一个是Orleans客户端, ...
- php 处理并发问题
对于商品抢购等并发场景下,可能会出现超卖的现象,这时就需要解决并发所带来的这些问题了 在PHP语言中并没有原生的提供并发的解决方案,因此就需要借助其他方式来实现并发控制. 方案一:使用文件锁排它锁 f ...