3 solutions

  • 1
    @ 2025-11-17 23:25:59

    首先想到应该是时间复杂度为O(n2n^2)的暴力枚举。读入a[],b[]两个数组,然后依次枚举每个位,让b[i]的取值为0并且把b[i]中的数据存储下来,从1开始枚举得到w的自小值,最后的答案是a[0]减去w的最小值。

    #include<iostream>
    using namespace std;
    const int N=1e5+10;
    int a[N],b[N];
    int main(){
        int n;cin>>n;
        for(int i=0;i<=n;i++){
            cin>>a[i];
        }
        for(int i=1;i<=n;i++){
            cin>>b[i];
        }
        for(int i=1;i<=n;i++){
            int x=b[i];b[i]=0;
            int w=0,ans=1e9;
            for(int j=1;j<=n;j++){
                w=w+b[j];
                w=w-a[j];
                ans=min(w,ans);
            }
            cout<<a[0]-ans<<" ";
            b[i]=x;
        }
        return 0;
    }
    

    暴力枚举只能过百分之八十的数据,接下来需要进行公式推导。w+i=1nbi1\sum_{i=1}^{n} b_{i-1}>=i=1nai\sum_{i=1}^{n} a_i,那w应该取 i=1nai\sum_{i=1}^{n} a_i-i=1nbi1\sum_{i=1}^{n} b_{i-1}的最大值,这里维护一个数组c[]来依次存储前面我们所说的差值。将b[i]的值赋为0并不影响前半部分的c[i],但是后半部分的c[i]需要再加一个b[i]。所以在这里维护一个数组pre[]存储前i个数中c[i]的最值,再维护一个数组suf[]存储后i个数的最值。最后答案的取值就是max(pre[i],suf[i]+b[i])。

    #include<iostream>//前缀和 
    using namespace std;
    const int N=1e5+10;
    int a[N],b[N],ans[N];
    int c[N],pre[N],suf[N];
    int main(){
    	int n;cin>>n;
    	for(int i=1;i<=n+1;i++)cin>>a[i];
    	for(int i=1;i<=n;i++)cin>>b[i];
    	pre[0]=suf[n+2]=-1e9;
    	for(int i=1;i<=n+1;i++){//需要自己进行公式推导 
    		c[i]=c[i-1]+a[i]-b[i-1];//c[i]是对a[i]求和-b[i]的最大值 
    		pre[i]=max(pre[i-1],c[i]);
    	}
    	for(int i=n+1;i;--i)suf[i]=max(suf[i+1],c[i]);//后缀的最大值 
    	for(int i=1;i<=n;i++){
    	ans[i]=max(pre[i],suf[i+1]+b[i]);//前缀不影响,后缀加上b[i]即可 
    	cout<<max(ans[i],0)<<" ";	
    	}
    	return 0;
    } 
    

    Information

    ID
    41
    Time
    1000ms
    Memory
    512MiB
    Difficulty
    2
    Tags
    # Submissions
    232
    Accepted
    54
    Uploaded By