打卡信奥刷题(3446)用C++实现信奥题 P10412 「QFOI R2」钟声远带斜阳
P10412 「QFOI R2」钟声远带斜阳
题目描述
注意:本题中的所有数列下标从 000 开始。
小 R 是一个可爱的女孩子,她喜欢研究无穷数列。
她称一个无穷数列 bbb 是美妙的,当且仅当存在自然数 k0k_0k0,使得对于所有 k≥k0k\ge k_0k≥k0,都满足 bbb 中下标在区间 [k0,k][k_0,k][k0,k] 内的所有数的和非负(即 ∑i=k0kbi≥0\sum_{i=k_0}^kb_i\ge 0∑i=k0kbi≥0)。例如,数列 αi=i−5\alpha_i=i-5αi=i−5 是美妙的,取 k0=5k_0=5k0=5 符合要求;但 βi=−i\beta_i=-iβi=−i 不是美妙的。
她目前只有一个长度为 nnn 的有穷数列 aaa,可以进行任意次以下三种操作:
- 花费 ppp 的代价,选择一个整数 iii(0≤i<n0\le i < n0≤i<n),将 aia_iai 增加一。
- 花费 qqq 的代价,选择一个整数 iii(0≤i<n0\le i < n0≤i<n),将 aia_iai 删除,同时更新 nnn 为新的数列长度。不能将数列删空。
- 花费 rrr 的代价,选择两个整数 i,ji,ji,j(0≤i<j<n0\le i < j < n0≤i<j<n),交换 aia_iai 与 aja_jaj。
她希望在若干次操作后,用无限个有穷数列 aaa 依次相接得到无穷数列 bbb(即 bi=ai mod nb_i=a_{i\bmod n}bi=aimodn),使得 bbb 是美妙的。请你求出最小的代价。
输入格式
第一行四个整数 n,p,q,rn,p,q,rn,p,q,r。
第二行 nnn 个整数,表示数列 aaa。
输出格式
一行,一个整数,表示最小代价。
输入输出样例 #1
输入 #1
5 1 2 5
2 -2 3 -3 -1
输出 #1
1
输入输出样例 #2
输入 #2
5 2 1 5
2 -2 3 -3 -1
输出 #2
1
输入输出样例 #3
输入 #3
5 1 1 1
0 1 2 3 4
输出 #3
0
说明/提示
样例 111 解释
花费 p=1p=1p=1 的代价将 a3a_3a3 增加一,得到数列 b=[2,−2,3,−2,−1,2,−2,3,−2,−1,⋯ ]b=[2,-2,3,-2,-1,2,-2,3,-2,-1,\cdots]b=[2,−2,3,−2,−1,2,−2,3,−2,−1,⋯] 是美妙的,取 k0=2k_0=2k0=2 符合要求。
可以证明不存在代价更小的方案。
样例 222 解释
花费 q=1q=1q=1 的代价将 a1a_1a1 删除,得到数列 b=[2,3,−3,−1,2,3,−3,−1,⋯ ]b=[2,3,-3,-1,2,3,-3,-1,\cdots]b=[2,3,−3,−1,2,3,−3,−1,⋯] 是美妙的,取 k0=0k_0=0k0=0 符合要求。
可以证明不存在代价更小的方案。
数据范围
本题采用捆绑测试。只有通过子任务中所有测试点以及所有依赖的子任务,才能获得相应的分数。
对于全部数据:1≤n≤1051\le n\le 10^51≤n≤105,1≤p,q,r≤1091\le p,q,r\le 10^91≤p,q,r≤109,∣ai∣≤109|a_i|\le 10^9∣ai∣≤109。
- 子任务一(101010 分):n=1n=1n=1。
- 子任务二(101010 分):n≤10n\le 10n≤10。依赖子任务一。
- 子任务三(202020 分):∣ai∣≤1|a_i|\le 1∣ai∣≤1。
- 子任务四(202020 分):∑∣ai∣≤105\sum|a_i|\le 10^5∑∣ai∣≤105。依赖子任务三。
- 子任务五(404040 分):无特殊限制。依赖子任务一、二、三、四。
C++实现
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
long long n,p,q,r,sum,ans,a[N];//要开 long long
bool f=true;//判断之前有没有用过修改操作
int main()
{
cin>>n>>p>>q>>r;
for(int i=1;i<=n;i++)
{
cin>>a[i];
sum+=a[i];
}
if (sum>=0)
{
cout<<0<<endl;
return 0;
}
sort(a+1,a+n+1);
for(int i=1;i<n;i++)
{
long long t=min(-sum,-a[i]);
if (q<t*p)//如果删除操作更优
{
ans+=q;
sum+=t;
}
else//如果修改操作更优
{
ans+=t*p;
sum+=t;
f=false;
}
if (sum>=0)
break;
}
if (a[n]<0)//不能删空
{
if (f)//如果之前都是删除操作,说明 a数组中只有啊 a[n]这一个数
ans+=(-a[n])*p;
else
ans+=min(q,(-a[n]*p));
}
cout<<ans<<endl;
}

后续
接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容
更多推荐



所有评论(0)