C. Maximum Subarray Sum
题目链接:https://codeforces.com/contest/2107/problem/C
题意:
给定一个长度为n的数组,和一个长度为n的01串,其中1代表该位置的数字是记得的,0代表该位置的数不记得
在不记得的数的位置上构造方案,使得最大子数组之和恰好为k
思路:
易知如果数组最大子数组已经大于k了,不成立
如果都记得,则无法填数,而最大子数组之和如果不等于k,那么不成立
其他情况都可以通过操作使数组满足条件
不如把不记得的位置都填入-inf,需要构造时选定一个位置temp,记它左边最大的连续相邻子数组和为A,右边最大连续相邻子数组和为B
A+a[temp]+B=k => a[temp]=k-A-B
这样只有这种情况子数组和最大且等于k,其他子数组都小于k
最大子数组和用dp求解
const int inf=1e13;
void solve(){
int n,k;cin>>n>>k;
string s;cin>>s;s=" "+s;
vector<int>a(n+1);
int cnt=0;
rep(i,1,n){
cin>>a[i];
if(s[i]=='0'){
a[i]=-inf;cnt++;
}
}
int big=0;
vector<int>dp(n+1);
rep(i,1,n){
dp[i]=max(dp[i-1]+a[i],a[i]);
big=max(big,dp[i]);
}
if(big>k||(cnt==0&&big!=k)){
cout<<"No"<<endl;return;
}
cout<<"Yes"<<endl;
if(cnt==0){
rep(i,1,n){
cout<<a[i]<<' ';
}
cout<<endl;return;
}
int temp=-1;
rep(i,1,n){
if(s[i]=='0')temp=i;
}
int mx1=0,mx2=0;
int pre=0,suf=0;
for(int i=temp+1;i<=n;i++){
suf+=a[i];
mx1=max(mx1,suf);
}
for(int i=temp-1;i>=1;i--){
pre+=a[i];
mx2=max(mx2,pre);
}
a[temp]=k-mx1-mx2;
rep(i,1,n){
cout<<a[i]<<' ';
}
cout<<endl;
}

浙公网安备 33010602011771号