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;
}
posted @ 2025-05-15 20:37  Marinaco  阅读(57)  评论(0)    收藏  举报
//雪花飘落效果