题解:P9292 [ROI 2018] Robomarathon

news/2025/10/28 19:51:57/文章来源:https://www.cnblogs.com/LTL0825/p/19172600

题目传送门

题目大意:

\(N\) 名机器人选手参加马拉松,选手编号为 \(1 \dots N\),分道编号也为 \(1 \dots N\)。选手 \(i\) 占据分道 \(i\),跑完全程需要 \(a_i\) 秒。

  • \(S \subseteq \{1, 2, \dots, N\}\) 表示初始发炮的分道集合。
  • 选手 \(i\) 的起跑时刻为:

    \[x_i = \min_{j \in S} |i - j| \]

  • 选手 \(i\) 的冲线时间为:

    \[f_i = a_i + x_i \]

  • \(i\) 的排名即为满足 \(f_j<f_i\)\(j\) 的个数 \(+1\)

\(p=1\) 时:对于每个选手 \(i\),求它的最好排名(最小)
\(p=2\) 时:对于每个选手 \(i\),求它的最坏排名(最大)

题目思路:

  1. \(p=1\)
    对于 \(p=1\) 很好考虑:直接在当前位置放一个,别的地方都不放,这对于当前的 \(i\) 是最优的。
    对于 \(i\) 来说,排名在其前的满足 \(a_j+ \left |i-j \right | < a_i\)
    \(j<i\) 时:\(a_j+i-j<a_i\)\(a_j-j<a_i-i\)。我们将 \(a_i-i\) 当作一个数丢入树状数组,每次从左到右扫一遍,对于当前的就查询 \(a_i-i-1\) 的前缀。
    \(j>i\) 时:\(a_j-i+j<a_i\)\(a_j+j<a_i+i\)。我们将 \(a_i+i\) 当作一个数丢入树状数组,每次从右到左扫一遍,对于当前的就查询 \(a_i+i-1\) 的前缀。
    将两次操作的和 \(+1\) 输出即可。
  2. \(p=2\)
    我们考虑先将所有跑道放上喇叭。
    假设 $i \le \left \lfloor \frac{n}{2} \right \rfloor $。
    对于当前位置 \(i\),我删去它的喇叭肯定会使 \(i\) 的排名不增,那我肯定删去它。
    若我同时在删去 \(i+1\)\(i-1\)。那么 \(i\)\(x_i =2\)\(i-1\)\(i+1\)\(x_i=1\) 别的 \(x_i\) 都是 \(0\),肯定会使 \(i\) 的排名不增,那我肯定删去它。
    重复这个流程,知道左边剩下一个 \(1\) 右边是 \(2\times i -1 \sim n\),这时不能再这样了,因为 \(1\) 删了就会导致 \(1\sim i-1\) 的发令喇叭变成 \(2\times i-1\) 不优。
    当然,我们还可以只放在 \(n\) 这个位置,这也是优的。
    所以,有两种:一种是放在 \(1\)\(2\times i -1 \sim n\) 另一种是放在 \(n\)
    对于右半部分,即 \(i>\left \lfloor \frac{n}{2} \right \rfloor\) 同理,可以自己试着推一下。\

代码 (详细注释,细节提醒)

#include<bits/stdc++.h>
#define int long long
#define OUT(x) cout<<"LINE: "<<__LINE__<<" INFO: "<<x<<'\n';
using namespace std;
int n,p;
int a[400010];
int tree[1600010];
int lowbit(int x)
{return x&-x;
}
void add(int x,int v)
{for(;x<=800000;x+=lowbit(x)){tree[x]+=v;}
}
int ask(int x)
{int ans=0;for(;x;x-=lowbit(x)){ans+=tree[x];}return ans;
}
int b[400010];
int c[400010];//ai+i
int d[400010];//ai-i
int ans[400010];
int ans1[400010];
struct node{int pos,val,op,q,add;
}kk[850010];
int e[800010];
int f[400010];
int g[400010];
void solve(int op)
{if(op == 0){int k=n/2;memset(tree,0,sizeof(tree));/*[1,i-1]的统计:满足fj<fi的j的数量 a[j]+i-j<a[i]a[j]-j<a[i]-i*/for(int i=1;i<=k;i++) {ans1[i]+=ask(c[i]-1);add(c[i],1);}memset(tree,0,sizeof(tree));int ll=0;/*这里是统计[i,2*i-1]:满足fj<fi的j的数量  我们发现,对于一个 i+1<=j<=2*i-1它要满足:a[j]+2*i-1-j<=a[i]+i-1a[j]-j<=a[i]-i所以我们需要知道,在[i,2*i-1]这个区间中,满足a[j]-j<=a[i]-i的j的数量那么我们将每个i的这种询问拆成两个询问:[1,2*i-1]满足a[j]-j<=a[i]-i的j的数量-[1,i-1]满足a[j]-j<=a[i]-i的j的数量,类似前缀查询这样就可以把这些询问记下来,按坐标排序,依次查询。我们还要把每个点加入进去,也就也是在i位置加入a[i]-inode成员的意义:pos:查询或加入的时间。val:查询或加入的值op:查询对对应i的贡献(i-1是-1,2*i-1是1,这样加一下就可以达到区间查询)q:查询对应哪个iadd:当前是加入还是查询 */ for(int i=k;i>=1;i--) {kk[++ll]={i-1,d[i]-1,-1,i,0};//拆询问 kk[++ll]={2*i-1,d[i]-1,1,i,0};}for(int i=1;i<=2*k-1;i++){kk[++ll]={i,d[i],1,1,1};//每个点要加入 }sort(kk+1,kk+ll+1,[](node x,node y){return x.pos==y.pos?x.add>y.add:x.pos<y.pos;});//排序,注意,当时间相同时,这里是先加入,在查询 for(int i=1;i<=ll;i++){if(kk[i].add)//加入 {add(kk[i].val,1);continue;}ans1[kk[i].q]+=kk[i].op*ask(kk[i].val);//查询 }/*[2*i,n]:满足fj<fi的j的数量  j要满足:f[j]<f[i]+i-1所以要将a[i]与a[i]+i-1离散化 这里需要小心一些(细节多)。我们从 floor(n/2) ~ 1枚举 当i%2 == 0时:我们每次加入a[i*2]和a[i*2+1],其中i=n/2时只能加入a[i*2]当i%2 != 0时:我们每次加入a[i*2]和a[i*2+1]每次查询a[i]+i-1的前缀 */ll=0;memset(tree,0,sizeof(tree));int len1=0;//离散化 for(int i=1;i<=n;i++){e[++len1]=a[i];e[++len1]=a[i]+i-1;}sort(e+1,e+1+len1);len1=unique(e+1,e+1+len1)-e-1;for(int i=1;i<=n;i++){f[i]=lower_bound(e+1,e+1+len1,a[i])-e;g[i]=lower_bound(e+1,e+1+len1,a[i]+i-1)-e;}if(k*2 == n)//进行操作 {for(int i=k;i>=1;i--){if(i == k){add(f[i*2],1);   }else{add(f[i*2],1);add(f[i*2+1],1);}ans1[i]+=ask(g[i]-1);}}else{for(int i=k;i>=1;i--){add(f[i*2],1);add(f[i*2+1],1);ans1[i]+=ask(g[i]-1);}}}else//右边同理,我就不说了 {int k=n/2+1;memset(tree,0,sizeof(tree));for(int i=n;i>=k;i--){ans1[i]+=ask(d[i]-1);add(d[i],1);}memset(tree,0,sizeof(tree));int ll=0;for(int i=k*2-n;i<=n;i++){kk[++ll]={i,c[i],1,1,1};}for(int i=k;i<=n;i++){kk[++ll]={2*i-n-1,c[i]-1,-1,i,0};kk[++ll]={i,c[i]-1,1,i,0};}sort(kk+1,kk+ll+1,[](node x,node y){return x.pos==y.pos?x.add>y.add:x.pos<y.pos;});for(int i=1;i<=ll;i++){if(kk[i].add){add(kk[i].val,1);continue;}ans1[kk[i].q]+=kk[i].op*ask(kk[i].val);}ll=0;memset(tree,0,sizeof(tree));int len1=0;for(int i=1;i<=n;i++){e[++len1]=a[i];e[++len1]=a[i]+n-i;}sort(e+1,e+1+len1);len1=unique(e+1,e+1+len1)-e-1;for(int i=1;i<=n;i++){f[i]=lower_bound(e+1,e+1+len1,a[i])-e;g[i]=lower_bound(e+1,e+1+len1,a[i]+n-i)-e;}if(k*2-n-1 == 1){for(int i=k;i<=n;i++){if(i == k){add(f[2*i-n-1],1);   }else{add(f[i*2-n-1],1);add(f[i*2-n-2],1);}ans1[i]+=ask(g[i]-1);}}else{for(int i=k;i<=n;i++){if(i == k){continue;}add(f[i*2-n-1],1);add(f[i*2-n-2],1);ans1[i]+=ask(g[i]-1);}}}
}
signed main()
{ios::sync_with_stdio(0);cin.tie(0);cin>>n>>p;for(int i=1;i<=n;i++){cin>>a[i];b[i]=a[i]+i;}//离散化 sort(b+1,b+1+n);int len=unique(b+1,b+1+n)-b-1;for(int i=1;i<=n;i++){c[i]=lower_bound(b+1,b+1+len,a[i]+i)-b;}for(int i=1;i<=n;i++){b[i]=a[i]-i;}sort(b+1,b+1+n);len=unique(b+1,b+1+n)-b-1;for(int i=1;i<=n;i++){d[i]=lower_bound(b+1,b+1+len,a[i]-i)-b;}if(p == 1){for(int i=n;i>=1;i--)//右->左 {ans[i]=ask(c[i]-1);add(c[i],1);}memset(tree,0,sizeof(tree));for(int i=1;i<=n;i++)//左->右 {ans[i]+=ask(d[i]-1);add(d[i],1);}for(int i=1;i<=n;i++){cout<<ans[i]+1<<'\n';//不要忘了+1 }//a[j]+i-j<a[i] -> a[j]-j<a[i]-i//a[j]+j-i<a[i] -> a[j]+j<a[i]+i}if(p == 2){for(int i=1;i<=n;i++)//左半部分,放在n的位置 {add(d[i],1);}for(int i=1;i<=n/2;i++){ans[i]=ask(d[i]-1);}memset(tree,0,sizeof(tree));for(int i=1;i<=n;i++)//右半部分,放在1的位置 {add(c[i],1);}for(int i=n/2+1;i<=n;i++){ans[i]=ask(c[i]-1);}solve(0);//左半部分 solve(1);//右半部分 for(int i=1;i<=n;i++){cout<<max(ans[i],ans1[i])+1<<'\n';//不要忘了+1,取的是max }}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/949095.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[题解]P5322 [BJOI2019] 排兵布阵

P5322 [BJOI2019] 排兵布阵 我们可以预处理出第 \(i\) 个城堡分配 \(j\) 的兵力能获得多少的得分,记为 \(w[i][j]\)。 则每一个 \(w[i]\) 都是一个泛化物品,即价值(\(w[i][j]\))随着分配体积(\(j\))变化的物品。…

申威服务器安装Nacos 2.0.3 RPM包详细步骤(Kylin V10 sw_64架构)​附安装包

申威服务器安装Nacos 2.0.3 RPM包详细步骤(Kylin V10 sw_64架构)​附安装包​ Nacos 2.0.3-1.ky10.sw_64.rpm​ 是专为 ​申威(SW)架构​ 处理器,并运行 ​中标麒麟操作系统 Kylin V10(64位)​​ 的服务器环境定…

ZKY精选冲刺省选国赛仿真训练题

求和 QOJ - 9902 解题思路 代码实现点击查看代码Bridges AtCoder - arc143_d 解题思路 代码实现点击查看代码龙门考古 UniversalOJ - 840 解题思路 代码实现点击查看代码Discrete Centrifugal Jumps CodeForces - 1407…

MySQL 查询与更新语句执行过程深度解析:从原理到实践​ - 指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

ZKY精选冲刺省选国赛技巧训练题

Discrete Centrifugal Jumps CodeForces - 1407D 解题思路 代码实现点击查看代码序列妙妙值 UniversalOJ - 549 解题思路 代码实现点击查看代码Constrained Sums AtCoder - abc277_h 解题思路 代码实现点击查看代码ag…

逆向基础--编码(001)

逆向基础--编码(001)一.位与字节比特(Bit):1比特就是1位,每个0或1就是一个位,位是数据存储的最小单位。位是二进制表示,8位二进制是一个字节。 8位二进制(就是8个比特)最大:11111111字节(Byte):字节是通过网…

20251027 - 倍增 ST表

前言: 怎么标题改来改去的? 概念 因为每一个整数都可以转换成对应的二进制,所以可以表示成 \(a_0 \times 2^0 + a_1 \times 2 ^ 1 + a_2 \times 2 ^ 2 + a_{len} \times 2 ^ {len}\)。 因此,对于求跳 \(x\) 步后的…

周康阳精选冲刺省选国赛思维训练题

agc052_a Long Common Subsequence 解题思路 代码实现点击查看代码agc052_a Long Common Subsequence 解题思路 代码实现点击查看代码agc052_a Long Common Subsequence 解题思路 代码实现点击查看代码agc052_a Long C…

Luogu P7913 [CSP-S 2021] 廊桥分配 题解 [ 绿 ] [ 贪心 ] [ 前缀和 ] [ STL ]

廊桥分配 笑点解析:VP 的时候想这题想了 20min,比想 T3 的时间长。 关键结论:在不考虑廊桥限制的情况下,给每个飞机分配一个最小的廊桥编号。当最终廊桥数目大于等于其对应编号时,飞机才能被分配到廊桥。 理解起来…

10-27 CSP 赛前比赛记录

DNA 序列(DNA)哈希题啊,但是忘了怎么写哈希了 qwq,所以…… 思路大概就是维护一个长度为 \(k\) 的四进制数,类似于一个滑动窗口,就是除以 \(4\) 后加上右边新加的数乘上 \(4^k\),就可以得到其对应的哈希值,取模…

P3939 数颜色

这道题是暑假写的。但是当时数据结构学傻了,写了个莫队。 然后刚刚发现没过,连忙重新看题。 想了想发现跟可以跟Ynoi有一道区间众数题一个思路处理一下,直接二分就完了。 就记录一下每个数的出现次数。这里还有个小…

完整教程:Docker 搭建 Nginx 并启用 HTTPS 具体部署流程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

AI开发微信小程序-有感

我先有一版html代码(有一个个人网站,里面都是一些在线使用的工具) 抽取出了其中一个小功能,让AI根据现有html代码直接转成小程序 直接拿过来在微信小程序开发IDE上,进行测试 稍微调整一下,就OK了。 AI真的是太有…

价值流智能时代:DevOps平台如何成为企业高效交付的核心引擎? - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2025年压力容器品牌综合实力排行榜

文章摘要 随着化工、石油、能源等行业的快速发展,压力容器作为核心设备在工业生产中扮演着越来越重要的角色。2025年压力容器行业将更加注重技术创新、安全性能与环保标准,头部企业通过智能化制造与定制化服务持续提…

2025年压力容器厂家综合评测与选择指南

摘要 随着化工、石油、能源等行业的快速发展,压力容器作为核心设备在工业生产中扮演着越来越重要的角色。2025年压力容器行业将更加注重技术创新、安全性能和服务质量,市场竞争也日趋激烈。本文基于行业数据和技术参…

2025年口碑好的压力容器工厂/厂家前十强

文章摘要 压力容器行业在化工、石油、动力及食品等领域持续增长,2025年预计全球市场规模将达千亿美元,驱动因素包括工业自动化升级和环保要求提升。本文基于行业数据、用户口碑和技术参数,综合评测前十品牌,并提供…

AI Agent 从零到百万价值迭代之路 - 智慧园区

这个时代Agent的本质:用精心设计的prompt作为"控制语句",用LLM作为"解释器",构建一个能处理模糊输入的动态系统-互联网创业老兵大模型时代为什么是革命 经过了近2年的Agent开发,在法律、工业、…

项目构建优化:CMake

CMake 介绍 在 Linux 工程管理中,make 是常用的工程管理器,但它依赖的 Makefile 语法晦涩、编写复杂,尤其在多文件、跨平台项目中维护成本极高。为解决这一问题,主流方案有两种:使用 automake 生成 configure 脚本…