数学考试

数学考试

题目描述

今天qwb要参加一个数学考试,这套试卷一共有n道题,每道题qwb能获得的分数为ai,qwb并不打算把这些题全做完, 他想选总共2k道题来做,并且期望他能获得的分数尽可能的大,他准备选2个不连续的长度为k的区间, 即[L,L+1,L+2,....,L+k-1],[R,R+1,R+2,...,R+k-1](R >= L+k)。
###输入描述:
第一行一个整数T(T<=10),代表有T组数据接下来一行两个整数n,k,(1<=n<=200,000),(1<=k,2k <= n)接下来一行n个整数a1,a2,...,an,(-100,000<=ai<=100,000)
###输出描述:
输出一个整数,qwb能获得的最大分数

输入

2
6 3
1 1 1 1 1 1
8 2
-1 0 2 -1 -1 2 3 -1

输出

6
7

题目大意

n道题,不做完,做2k道,连续两个不重合长度为k的区间,分数最大

思路

dp+前缀和
1.先求前缀和
2.从前到后求出数组下标i前的最大k长度区间和,不断更新(前一个的最大和最当前的和进行比较)
3从后到前求出数组下标i后的最大k长度区间和,不断更新(后一个的最大和最当前的和进行比较)
4.枚举所有i的前后最大值的和,找出最大和

错误思路

先求最大的k长度区间和,再从两边找第二大的k长度区间和
错误原因:情况考虑不全。

/*#include<bits/stdc++.h>错误思路
using namespace std;
int num[2000005];
struct date{
    int a;
    int head;
    int wei;
}sum[2000005];
bool cmp(date a,date b)
{
    return a.a>b.a;
}
int main()
{
    //n道题 每道ai分 不全部做完,做2k道题,分数尽可能大
    //前缀和
    //不重合的两个区间 
    int t;
    scanf("%d",&t);
    while(t--)
    {
        for(int i=0;i<2000005;i++)//初始化 
        {
            num[i]=0;
            sum[i].a=0;
            sum[i].head=0;
            sum[i].wei=0;
        }
        int n=0,k=0;
        scanf("%d%d",&n,&k);
        for(int i=0;i<n;i++)
        {
            scanf("%d",&num[i]);
        }
        for(int i=0;i<k;i++)
        {
            sum[0].a=sum[0].a+num[i];
        }
        sum[0].head=0;
        sum[0].wei=k-1;
        //printf("sum[0]=%d\n",sum[0]); 
        for(int i=1;i<n&&sum[i].wei<n;i++)
        {
            sum[i].a=sum[i-1].a+num[sum[i-1].wei+1]-num[sum[i-1].head];
            sum[i].head=sum[i-1].head+1;
            sum[i].wei=sum[i-1].wei+1;
        }
        sort(sum,sum+n,cmp);
        int max=sum[0].a;
        sum[0].a=0;
        int maxn=0;
        for(int i=0;i<n;i++)
        {
            if(sum[i].a>maxn)
            {
                if(sum[i].head>sum[0].wei||sum[i].wei<sum[0].head)
                {
                    maxn=sum[i].a;
                }
            }
        }
        printf("%d\n",max+maxn);
     } 
    return 0;
 } */
#include<bits/stdc++.h>
using namespace std;
long long int sum[200005];
long long int f[200005];
long long int s[200005];
int main()
{
    //dp记录下标i前最大的值,i后最大的值 
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,k;
        long long ans=-1e18;
        scanf("%d%d",&n,&k);
        memset(f,-0x7f,sizeof(f)) ;
        memset(s,-0x7f,sizeof(s));
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&sum[i]);
            sum[i]=sum[i]+sum[i-1];
        }
        for(int i=k;i<=n-k;i++)
        {
            f[i]=max(f[i-1],sum[i]-sum[i-k]);
        }
        for(int i=n-k+1;i>=k+1;i--)
        {
            s[i]=max(s[i+1],sum[i+k-1]-sum[i-1]);
        }
        for(int i=k;i<=n-k;i++)
        {
            ans=max(ans,f[i]+s[i+1]);
        }
        printf("%lld\n",ans);
    }
    return 0;
}
全部评论

相关推荐

1 收藏 评论
分享
牛客网
牛客企业服务