请问一个问题:带限制的连续子数组最大和
如题:给一个有n个整数的数组a[],给一个m,要你求出在数组中最多取m个连续的数能获得的最大和。题目链接:https://acm.uestc.
程序代码:#include <stdio.h>
long long foo( const int a[], size_t n, size_t m )
{
long long ans = a[0];
long long sum = a[0];
size_t left = 0;
for( size_t i=1; i!=n; ++i )
{
if( i-left < m )
{
if( sum<=0 || sum+a[i]<=0 )
{
left = i;
sum = a[i];
}
else
{
sum += a[i];
}
}
else
{
long long tmp_maxsum = 0;
size_t tmp_left = i;
long long tmp_sum =0;
for( size_t j=i-1; j>left; --j )
{
tmp_sum += a[j];
if( tmp_maxsum < tmp_sum )
{
tmp_maxsum = tmp_sum;
tmp_left = i;
}
}
sum = tmp_maxsum + a[i];
left = tmp_left;
}
if( ans < sum )
ans = sum;
}
return ans;
}
int main( void )
{
size_t n, m;
scanf( "%zu%zu", &n, &m );
int a[100000];
for( size_t i=0; i!=n; ++i )
scanf( "%d", &a[i] );
printf( "%lld\n", foo(a,n,m) );
}
程序代码:#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
const long long inf = 0x3f3f3f3f3f3f3f3fLL;
long long a[N], sum[N], tree[N<<2];
void pushup(int rt)
{
tree[rt] = min(tree[rt<<1], tree[rt<<1|1]);
}
void build(int l, int r, int rt)
{
if (l == r){
tree[rt] = sum[l];
return;
}
int mid = (l+r) >> 1;
build(l, mid, rt<<1);
build(mid+1, r, rt<<1|1);
pushup(rt);
}
long long query(int L, int R, int l, int r, int rt)
{
if (L <= l && r <= R){
return tree[rt];
}
int mid = (l+r) >> 1;
long long ans = inf;
if (L <= mid) ans = min(ans, query(L, R, l, mid, rt<<1));
if (R > mid) ans = min(ans, query(L, R, mid+1, r, rt<<1|1));
return ans;
}
signed main(void)
{
ios::sync_with_stdio(false), cin.tie(0);
int n, m;
long long mx = -inf;
cin >> n >> m;
for (int i = 1; i <= n; ++i){
cin >> a[i];
mx = max(mx, a[i]);
sum[i] = sum[i-1] + a[i];
}
if (mx <= 0){
cout << mx << endl;
return 0;
}
build(0, n, 1);
long long ans = 0;
for (int i = 1; i <= n; ++i){
int s = (i - m >= 0) ? i-m : 0;
ans = max(ans, sum[i]-query(s, i, 0, n, 1));
}
cout << ans << endl;
return 0;
}