当前位置: 首页 > news >正文

P10806 [CEOI 2024] 洒水器 题解

P10806 [CEOI 2024] 洒水器 题解

思路

首先可以想到二分答案,难点在于如何判断合法。

首先考虑贪心,如果洒水器前面还有花没浇则向左转,否则向右转。

贪心代码1 check 部分

bool check(int k){int p=1;for(int i=1;i<=n&&p<=m;i++){if(f[p]<s[i]){if(s[i]-k>f[p])return 0;while(f[p]<=s[i]&&p<=m)p++;}else{while(f[p]<=s[i]+k&&p<=m)p++;}}return p>m;
}

提交之后会获得 9 分的高分,考虑如何优化贪心。

注意到以下情况:

按照原本的贪心思路,当喷水强度为 3 时,两个洒水器都会向左旋转,第三个花无法被浇到,就像下面这张图片显示的那样。

此时如果我们将第一个洒水器向右旋转,发现可以浇完全部的花,就像下面这张图片显示的那样。

那么是什么时候会向右旋转呢?注意到第二个洒水器如果向左旋转,那么原本第一个洒水器需要浇的花已经被第二个洒水器浇了,所以第一个洒水器就可以向右旋转了。

贪心代码2 check 部分

bool check(int k){int p=1;for(int i=1;i<=n&&p<=m;i++){if(f[p]<s[i]){pre[i]=f[p];ans[i]='L';if(s[i]-k>f[p])return 0;while(f[p]<=s[i]&&p<=m)p++;if(ans[i-1]=='L'&&pre[i-1]>=s[i]-k){pre[i]=pre[i-1];ans[i-1]='R';while(f[p]<=s[i-1]+k&&p<=m)p++;}}else{ans[i]='R';while(f[p]<=s[i]+k&&p<=m)p++;}}return p>m;
}

交上去发现只有 73 分,这是为什么呢?

注意到有一组 hack:

3 5
1 8 13
0 7 9 10 15

你输出的可能是正确答案 7,但是如果 check 一下答案 8,会返回 0,这又是为什么呢?

因为当喷水强度为 8 时,第二个洒水器就会让第一个洒水器向右旋转,最终无法浇到全部的花。

假如有一段连续往左旋转的洒水器:

LLLLLLLLLLLLLLL

则倒数第一和倒数第二个洒水器之间一定有一个洒水器不能被倒数第三个洒水器向右旋转覆盖到(否则倒数第一个洒水器就会向左旋转),此时将倒数第二个洒水器向右旋转是最优的,因为如果第二个洒水器向左旋转,倒数第一个洒水器也需要向左旋转,就无法浇到右边的花了。

以此类推,我们需要从后往前找可以向右旋转的洒水器即可。

贪心代码3 check 部分

bool check(int k){int p=1;for(int i=1;i<=n&&p<=m;i++){if(f[p]<s[i]){//如果左边还有花需要浇pre[i]=f[p];ans[i]='L';if(s[i]-k>f[p]){return 0;}while(f[p]<=s[i]&&p<=m)p++;//该洒水器向左旋转可以浇到的花if(ans[i-1]=='L'&&pre[i-1]>=s[i]-k){//如果有多个连续的Lvis[i]=1;//此处仅做记录,后面再统一处理连续的Lwhile(f[p]<=s[i-1]+k&&p<=m)p++;//要么该洒水器向右旋转,要么前一个洒水器向右旋转,至少会浇到s[i-1]+k的花}}else{ans[i]='R';while(f[p]<=s[i]+k&&p<=m)p++;}}for(int i=n;i>=1;i--)if(vis[i]){vis[i]=vis[i-1]=0;//注意不能有两个连续的L变Rans[i-1]='R';}return p>m;
}

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m,s[100010],f[100010],pre[100010],ans[100010],vis[100010];
bool check(int k){int p=1;for(int i=1;i<=n&&p<=m;i++){if(f[p]<s[i]){pre[i]=f[p];ans[i]='L';if(s[i]-k>f[p]){return 0;}while(f[p]<=s[i]&&p<=m)p++;if(ans[i-1]=='L'&&pre[i-1]>=s[i]-k){vis[i]=1;while(f[p]<=s[i-1]+k&&p<=m)p++;}}else{ans[i]='R';while(f[p]<=s[i]+k&&p<=m)p++;}}for(int i=n;i>=1;i--)if(vis[i]){vis[i]=vis[i-1]=0;ans[i-1]='R';}return p>m;
}
int main(){ios::sync_with_stdio(false);cin.tie(0);cin>>n>>m;for(int i=1;i<=n;i++){cin>>s[i];ans[i]='R';}for(int i=1;i<=m;i++){cin>>f[i];}int l=0,r=1e9;while(l<r){int mid=(l+r)>>1;if(check(mid))r=mid;else l=mid+1;}if(check(r))cout<<r<<'\n';else{cout<<-1;return 0;} for(int i=1;i<=n;i++){cout<<(char)ans[i];}return 0;
}
http://www.dtcms.com/a/438784.html

相关文章:

  • 温州十大网络公司排名广州网站建设专业乐云seo
  • 做礼品的网站中航长江建设工程有限公司网站
  • SQL ROUND() 函数详解
  • RK3588 SSH相关方法总结(每次遇到问题更新)
  • 国家基础设施建设网站杨园建设社区网站
  • 3. 是网站建设的重点亿唐网不做网站做品牌原因
  • C# TCP 开发笔记(TcpListener/TcpClient)
  • 成都网络优化公司排行榜网站的优化是什么
  • 山西网站建设多少钱怎么做旅游网站
  • JAVA第八学:继承和多态
  • 网站开发前端指什么太原本地网站搭建公司
  • FastAPI 路径操作依赖项
  • wordpress开发网站美业营销策划公司
  • 《强化学习数学原理》学习笔记5——压缩映射定理的证明
  • Mysql速成笔记2(DML)
  • 网站流量如何增加东莞服务
  • pv-pvc-sc存储卷进阶-sts-helm资源清单基础管理
  • 什么是网站站点建设介绍网上营销新观察网
  • 吃透大数据算法-字典编码(Dictionary Encoding)
  • 从pty驱动学习tty设备驱动加载
  • 车牌号黑名单校验功能实现说明
  • 【第五章:计算机视觉-项目实战之生成对抗网络实战】2.基于SRGAN的图像超分辨率实战-(1)实战1:人脸表情生成实战任务详解
  • 【双指针专题】之快乐数
  • 锦州滨海新区城市建设规划网站建设局是个好单位吗
  • 域名搭建网站域名一般在哪里购买
  • 拦截器Interceptor
  • 运营网站流程ui设计的定义
  • 可以做自己的单机网站网站客户案例的
  • 网络编程中UDP协议的广播和组播通信
  • STM32G474单片机开发入门(一)STM32G474RET6单片机详解