【AtCoder】【模拟】【模型转化】Camel and Oases(AGC012)

2023-05-16

题意:

有一个骆驼,n个绿洲遍布在数轴上,第i个绿洲的坐标为x[i],保证x[i]单增。骆驼的驼峰有体积初始值V。当驼峰的体积变为v的时候,驼峰中至多只能够存储v L的水。骆驼希望走完所有的绿洲,并且可以向下面这样来走:
1.走距离d,消耗驼峰中d L的水,但是驼峰的体积不会减少。任意时候驼峰中的水的体积均不能够为负数;
2.跳跃到任意一个位置,消耗完所有的水,并且让驼峰的体积变为v/2。该操作在v=0的时候是不能够进行的。
骆驼能够在绿洲将水补满至v。且一个绿洲可以多次访问并进行补给。最后要求你输出从每个位置出发,能否走完所有的绿洲。

数据范围:

N,V<=2*1e5 ,-1e9<=x[i]<=1e9 ,且x是单增的。

思路:

首先看完题目,我们可以发现v/2这个操作是十分玄学的。这意味着只会减少log(V)+1次,就不能够再进行任何的移动了。也说明了v的取值只会有log(V)+2种,这个数量级是很小的。
那么对于某一个v而言,骆驼能够在一些连续的绿洲之间任意的穿梭,也就形成了一些线段。具体而言就是假如说x[i+1]-x[i]<=v,那么这两个绿洲就是联通的,就可以让i和i+1处于一条线段中。我们可以发现,当v从V变换到0的时候,每一条线段的长度是在逐渐变短的,而线段的数量在逐渐增多。也就是说,v越小,骆驼的移动能力越差。现在这个问题就变成了强迫你选择了第一层(也就是v=V的那一层)中的某一条线段,在剩下的每一层当中,选出至多一条线段,能否存在一种方式使得最后选出来的所有的线段能够覆盖完所有的绿洲。
对于这个问题而言,瞬间就简化了不少。可以定义f1[state],表示在选择state(第i位为0表示第i层没有选择线段,第i位为1表示第i层选择了一条线段)的时候,(线段从最左边开始选)能够覆盖完全的最靠右的位置;定义f2[state],表示在选择state的时候,(线段从最右边开始选)能够覆盖完全的最靠左的位置。最后再扫一遍第一层中的所有的线段,表示强行选择其中的某一条线段,然后找是否有一个state,满足第0位不为1(第一层已经被确定了),且f1[state],f2[全集-state-1],加上这条线段,使得能够覆盖完所有的绿洲。
这样子看上去似乎问题已经解决了,但是当V奇小的时候,第一层最坏可能有n条线段(一个点一条),然后就变成了 O ( n 2 l o g n ) = O ( n 2 ) O(n2^{log_n})=O(n^2) O(n2logn)=O(n2)的状态。仔细分析之后,我们可以发现,假如第一层的线段数量大于了logV+2,那么由于接下来的线段只会越来越短并且越来越多,就算是选择第一层的所有线段也需要>logV+2条线段,而一共才能够选择log(V)+2条线段线段,那就显然不可能有解了。全部输出Impossible即可。
这样子就变为了O(logV * n)的时间复杂度了。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 1000000
#define INF 2000000000
using namespace std;
int n,V,x[MAXN+5];
int cnt[25];//cnt用于计算每一层所有的线段数
int l[25][MAXN+5],r[25][MAXN+5];//l表示线段的左端点,r表示的则是右端点
int f1[MAXN*5+5],f2[MAXN*5+5];//如思路中的定义
bool ans[MAXN+5];//ans记录的是对于某一条线段的答案,不是某个绿洲的答案
void Init()
{
	for(int i=0;i<=MAXN*5+3;i++)
		f1[i]=0,f2[i]=INF;
}
int UpFind(int id,int pos)//找l在pos+1的左边的线段,也就是能够向右扩展的最靠右的线段
{
	pos++;
	int p=upper_bound(l[id]+1,l[id]+cnt[id]+1,pos)-l[id];
	p--;
	if(p<=0)
		return pos;
	return max(r[id][p],pos-1);
}
int LowFind(int id,int pos)//找r在pos-1的右边的线段,也就是能够向左扩展的最靠左的线段
{
	pos--;
	int p=lower_bound(r[id]+1,r[id]+cnt[id]+1,pos)-r[id];
	if(p>=cnt[id]+1)
		return pos;
	return min(l[id][p],pos+1);
}
int main()
{
	Init();
	scanf("%d %d",&n,&V);
	int logV=0;
	for(logV=0;(1<<logV)<=V;logV++);//求出来的实际上是logV+1
	for(int i=1;i<=n;i++)
		scanf("%d",&x[i]);
	x[n+1]=INF;
	x[0]=-INF;//便于操作
	for(int LG=0;LG<=logV;LG++)
	{
		int d=V/(1<<LG);
		cnt[LG]=1;
		l[LG][1]=1;
		//求线段
		for(int i=1;i<=n;i++)
		{
			r[LG][cnt[LG]]=i;
			if(x[i+1]-x[i]>d)
			{
				cnt[LG]++;
				l[LG][cnt[LG]]=i+1;
			}
		}
		cnt[LG]--;
	}
	if(cnt[0]>logV+1)//特判
	{
		for(int i=1;i<=n;i++)
			printf("Impossible\n");
		return 0;
	}
	int all=(1<<(logV+1));
	f1[0]=0,f2[0]=n+1;//预处理两个f数组
	for(int s=0;s<all;s+=2)
		for(int i=0;i<=logV;i++)
		{
			if(!(s&(1<<i)))
				continue;
			f1[s]=max(f1[s],UpFind(i,f1[s-(1<<i)]));
			f2[s]=min(f2[s],LowFind(i,f2[s-(1<<i)]));
		}
	for(int i=1;i<=cnt[0];i++)//枚举第一层的每一条线段
	{
		int ln=l[0][i],rn=r[0][i];
		for(int s1=0;s1<all;s1+=2)
		{
			int s2=all-1-s1-1;
			int lpos=f1[s1];
			int rpos=f2[s2];
			if(lpos>=ln-1&&rpos<=rn+1)//看能否覆盖所有的绿洲
			{
				ans[i]=true;//存的是线段的答案
				break;
			}
		}
	}
	int pos=1;
	for(int i=1;i<=n;i++)
	{
		if(ans[pos]==true)
			printf("Possible\n");
		else
			printf("Impossible\n");
		if(x[i+1]-x[i]>V)
			pos++;
	}
	return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【AtCoder】【模拟】【模型转化】Camel and Oases(AGC012) 的相关文章

随机推荐

  • 超级有用的git reset --hard和git revert命令

    很多时候 xff0c git新手容易误操作 xff0c 比如 xff0c 在levelIISZ 1 4 dev分支下 xff0c 运行了git pull idc cpp 1 0的结果 xff0c 这样做麻烦很大 xff0c 经常导致mave
  • android 为什么需要签名

    所有的Android应用程序都要求开发人员用一个证书进行数字签名 xff0c anroid系统不会安装没有进行签名的由于程序 平时我们的程序可以在模拟器上安装并运行 xff0c 是因为在应用程序开发期间 xff0c 由于是以Debug面试进
  • 高通平台工具使用

    OverView QPST 综合工具 传输文件 查看 device 的 EFS 文件系统 代码烧录 QRCT 测试RF QXDM 看log JTAG trace32调试 QPST QXDM的使用说明 xff0c 具体的可以看我上传到csdn
  • git创建与管理远程分支

    1 远程分支就是本地分支push到服务器上的时候产生的 比如master就是一个最典型的远程分支 xff08 默认 xff09 1 git push origin master 除了master之外 xff0c 我们还可以随便创建分支 xf
  • pthread_key_t和pthread_key_create()详解

    下面说一下线程中特有的线程存储 xff0c Thread Specific Data 线程存储有什么用了 xff1f 他是什么意思了 xff1f 大家都知道 xff0c 在多线程程序中 xff0c 所有线程共享程序中的变量 现在有一全局变量
  • 2016 Personal Training #11 Div.2 B G J

    UVALive 5963 题意 xff1a 给你n个数 xff0c 如果这n个数满足 xff1a 例如n 61 4第一个数前面有0个数后面有三个数那么这第一个位置数可以为0或者3 xff0c 第二个位置可以为1或2等等 给出的n个数满足则输
  • Ubuntu22.04安装CUDA11.8和CUDNN

    下载CUDA11 8 下载CUDA11 8 选择对应的系统 架构 OS 版本 逐步执行上图命令 编辑环境变量文件 sudo gedit bashrc 配置环境变量 export PATH 61 usr local cuda 11 8 bin
  • ACME.SH 申请SSL证书(免费、自动更新)

    1 获取DNS密钥 xff08 1 xff09 获取域名服务商AccessKey ID及AccessKey Secret 我使用的域名是阿里云 xff0c 故需要去阿里云RAM管理平台获取 xff1a 其他服务商 xff0c 可以去指定的服
  • C语言fscanf函数读取结构化数据

    函数原型 xff1a int fscanf FILE restrict stream const char restrict format span class hljs keyword span fscanf 分隔符是 空格 tab 回车
  • 选择法排序

    选择法排序 xff1a 假设有N个数要按照从大到小的顺序排序 xff0c 选择法就是先设第一个数是最大的 xff08 进行第一次大循环 xff09 xff0c 然后将这个数与数组中剩下的数依次比较 xff0c 如果剩下的数中有比这个数大的
  • debian 10的安装DVD

    准备 下载debian 链接 xff1a https pan baidu com s 1BfyVmF3UgiEyKWzgQO90LA 提取码 xff1a evk9 复制这段内容后打开百度网盘手机App xff0c 操作更方便哦 来自百度网盘
  • Linux 最常用命令汇总

    常用命令 一 文件操作进入文件夹查看文件夹下文件创建文件夹复制文件移动文件删除文件查看文件内容实时查看文件内容创建文件编辑文件追加文件内容添加文件内容替换文件内容清空文件压缩解压文件分割文件文件合并文件对比显示文件树软链接一次执行多个she
  • CSP官网题目——炉石传说

    问题描述 玩家会控制一些角色 xff0c 每个角色有自己的生命值和攻击力 当生命值小于等于 0 时 xff0c 该角色死亡 角色分为英雄和随从 玩家各控制一个英雄 xff0c 游戏开始时 xff0c 英雄的生命值为 30 xff0c 攻击力
  • 【C51自学笔记】定时器

    CPU时序 xff1a v 振荡周期 xff1a 为单片机提供定时信号的振荡源的周期 xff08 晶振周期或外加振荡周期 xff09 v 状态周期 xff1a 2个振荡周期为1个状态周期 xff0c 用S表示 振荡周期又称S周期或时钟周期
  • Codeforces Round #706 (Div. 2)

    代码 xff1a span class token macro property span class token directive keyword include span span class token string lt iost
  • Codeforces Round #366 (Div. 2) A和B

    昨晚打了一个小时CF感悟最大的就是英文真是菜的抠脚 xff0c 第二题看了半天再结合样例解释才知道是什么意思 xff0c 第一题第一次提交代码输出漏写个单词真是醉了 xff0c 两题都掉分果真CF A Hulk 题意 xff1a 如果是1就
  • Matlab进行多项式的因式分解

    clear all span class token punctuation span clc syms x span class token punctuation span f1 span class token operator 61
  • 【linux】详解linux 下安装软件tar.gz, rpm,deb的方法

    在Linux系统中 xff0c 软件安装程序比较纷繁复杂 xff0c 不过最常见的有两种 xff1a 1 xff09 一种是软件的源代码 xff0c 您需要自己动手编译它 这种软件安装包通常是用gzip压缩过的tar包 xff08 后缀为
  • 有n个人围成一圈,顺序排号。从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第 几号的那位。

    问题 xff1a 有n个人围成一圈 xff0c 顺序排号 从第一个人开始报数 xff08 从1到3报数 xff09 xff0c 凡报到3的人退出圈子 xff0c 问最后留下的是原来第 几号的那位 解决思路 我的解决思路是先给这n个人排序生成
  • 【AtCoder】【模拟】【模型转化】Camel and Oases(AGC012)

    题意 xff1a 有一个骆驼 xff0c n个绿洲遍布在数轴上 xff0c 第i个绿洲的坐标为x i xff0c 保证x i 单增 骆驼的驼峰有体积初始值V 当驼峰的体积变为v的时候 xff0c 驼峰中至多只能够存储v L的水 骆驼希望走完