环上最大连续和

环上最大连续和

给定N,K以及一个环:A[1],A[2],A[3],…A[N],其中A[1]的左边是A[N]。
求该环上最大的连续子段和,要求选出的子段长度不超过K。

输入描述:
第一行两个整数N和K。
接下来一行,N个整数表示A[i]。

输出描述:
输出题目要求的最大连续和。

链接:
https://www.nowcoder.com/questionTerminal/8db855bdae5b426cb08cab6b5e119d26

解析

普通的最大连续和用简单的dp就可以解决了。本题还要求这个最大连续和的序列长度不超过K。我们首先维护一个数组A的前缀和sum, 这样一来求区间 [ l , r ] [l,r] [l,r]的和就为: s u m [ r ] − s u m [ l − 1 ] sum[r]-sum[l-1] sum[r]sum[l1], 最大连续和问题可以转化为对于每个i,找到最小的j,满足 j − i < = k j-i<=k ji<=k即可,即可转化为单调队列问题,用优先队列维护前缀和的最小值即可.

AC代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define INF 0x3f3f3f
#define MEM0(a) memset(a,0,sizeof(a))
#define MEM1(a,b) memset(a,b,sizeof(b)
#define FOR0(a,b) for(int i=a;i<=b;i++)
#define FOR1(a,b) for(int i=a;i
#define FOR2(a,b) for(int i=a;i>=b;i--)
#define FOR3(a,b) for(int i=a;i>b;i--)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn=2e5+5;
const int maxm=1e5+5;
const int mod=1e9+7;
const int inf=1e9;
const double eps=1e-9;
const double PI=acos(-1.0);
int a[maxn];
struct node{
    int id,x;
    node(){};
    bool operator<(const node& tmp)const{
        return tmp.x<x;
    }
}sum[maxn];
priority_queue<node> qq;

inline int min(int x,int y){
    return x<y?x:y;
}
inline int max(int x,int y){
    return x>y?x:y;
}

int main(){
    int n,k;
    scanf("%d %d",&n,&k);
    sum[0].id=0,sum[0].x=0;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        sum[i].id=i;
        sum[i].x=sum[i-1].x+a[i];       //求前缀和;
    }
    for(int i=n+1;i<=n+k;i++){
        sum[i].id=i;
        sum[i].x=sum[i-1].x+a[i-n];
    }
    
    int ans=-inf;
    qq.push(sum[0]);
    for(int i=1;i<=n+k;i++){
        qq.push(sum[i]);
        while(i-qq.top().id>k){
            qq.pop();
        }
        ans=max(ans,sum[i].x-qq.top().x);
    }
    printf("%d\n",ans);
    return 0;
}

你可能感兴趣的:(算法类,单调队列)