专栏文章
怎么都写的这么复杂。
P3470题解参与者 12已保存评论 13
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 13 条
- 当前快照
- 1 份
- 快照标识符
- @mindv2aa
- 此快照首次捕获于
- 2025/12/02 00:48 3 个月前
- 此快照最后确认于
- 2025/12/02 00:48 3 个月前
模拟赛切了,来发儿子点的题解。
sol
手玩一下这个循环右移操作,记这个 的前缀和数组为 。
记这个 数组里的值的最小值为 ,你考虑一次右移对这个 的影响是啥。
手玩发现右移一个 是给所有原来是 的位置 ,右移一个 是给所有原来是 的位置 。
那么这个时候你就发现,右移一个加号给一个减号的位置 ,那么最小值是不是就是 了?
实际上是不对的,因为一个最小值的出现一定是 的一个交界处,实际上应该是最小值 。
同理可得如果右移的是 那么应该是最小值 。
那么这个时候就没啥难度了,你就可以枚举你用几次右移操作,然后你就知道你的最小值和总共的和了。
总共的和肯定要等于 。
根据经典贪心暴力选最前面的 改,算一下它对最小值的影响。
其实可以不用管,你直接把末尾的加号给改成 一定不会使最小值变为负的。
然后每次对最小值 用 的代价,这个也好 算。
做完了,复杂度 。
但是这个地方有一点要提,如果这个 是在 的,你循环右移是不会将其 的。
但是这个对于我们答案完全没有影响,因为 必须要等于 。
代码细节有点多,我还是给一下:
CPP#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=1e9+7;
int n,p,q,x,y,m,ans=INT_MAX,sum,a[1000001],mxl,mxr,mn=INT_MAX;
string s;
signed main(){
// freopen("book.in","r",stdin);
// freopen("book.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>p>>q>>x>>y>>s;
// assert(s.size()==n);
s=" "+s;
a[0]=p;
for(int i=1;i<=n;i++){
a[i]=a[i-1]+(s[i]=='+'?1:-1);
// cout<<a[i]<<" ";
if(i!=n) mn=min(mn,a[i]);
}
// cout<<'\n';
int l=n,sm=a[n];
// assert(!((q-sm)&1));
for(int i=1;i<=n;i++){
int vl=mn,val=(i-1)*y;
if(sm<q) val+=(q-sm)/2*x,vl+=(q-sm);//改最前面的减号。
else if(sm>q)val+=(sm-q)/2*x;//改最后面的正号。
if(vl>=0) ans=min(ans,val);
else val+=(-vl+1)/2*2*x,ans=min(ans,val);
if(s[l]=='-') mn--;
else if(s[l]=='+')mn++;
l--;
}
cout<<ans;
return 0;
}
/*
首先肯定要通过改位去把整个串的和给改为 p。
9 0 3 4 1
---+-++--
*/
相关推荐
评论
共 13 条评论,欢迎与作者交流。
正在加载评论...