HDU Max Sum of Max-K-sub-sequence 单调队列

  • Max Sum of Max-K-sub-sequence

  • 题意
    给出一个有N个数字(N<=10^5)的环状序列,让你求一个和最大的连续子序列。这个连续子序列的长度小于等于K。

  • 思路
    借鉴的这位大佬的博客
    看完思路,结果敲WA了。 然后看了看大佬的代码后有一点不是很理解,遍历的是i,为什么将对sum[i-1]进行操作,最后求tmp的时候,又用到了sum[i], 后来想明白了。
    假如遍历到了i,用单调队列维护的是区间 [ s u m [ i − k ] , s u m [ i + 1 − k ] . . . , s u m [ i − 1 ] ] [sum[i-k],sum[i+1-k]...,sum[i-1]] [sum[ik],sum[i+1k]...,sum[i1]]这k个数的最小值,这个最小值的下标作为满足条件区间的左端点,而i是右端点。这个区间的大小是小于等于k的。考虑极端情况 s u m [ i − k ] sum[i-k] sum[ik]的值最小,tmp= s u m [ i ] − s u m [ i − k ] sum[i]-sum[i-k] sum[i]sum[ik]的值是数列中[i-k+1,i]这k个数的和。所以每次尝试填入队列的是sum[i-1],最后求tmp的时候用到了sum[i].

  • 代码

#pragma GCC optimize(2)
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long ul;
typedef unsigned long long ull;
#define pi acos(-1.0)
#define e exp(1.0)
#define pb push_back
#define mk make_pair
#define fir first
#define sec second
#define scf scanf
#define prf printf
typedef pair<ll,ll> pa;
const ll INF=0x3f3f3f3f3f3f3f3f;
const ll MAX_T=120;
const ll MAX_N=1e5+7;
ll a[MAX_N],sum[MAX_N<<1],N,K,T;
deque<ll>DQ;
int main()
{
    
    
//  freopen(".../.txt","w",stdout);
//  freopen(".../.txt","r",stdin);
   ios::sync_with_stdio(false);
   cin>>T;
   while(T--){
    
    
   	cin>>N>>K;
   	DQ.clear();
   	ll i,j,k,maxx=-INF,resl=-1,resr=-1;
   	sum[0]=0;
   	for(i=1;i<=N;i++){
    
    
   		cin>>a[i];
   		sum[i]=sum[i-1]+a[i];
   	}
   	for(i=1;i<=K;i++){
    
    
   		sum[i+N]=sum[i+N-1]+a[i]; 
   	}
   	for(i=1;i<=N+K-1;i++){
    
    
   		while(!DQ.empty()&&sum[i-1]<sum[DQ.back()]){
    
    
   			DQ.pop_back();
   		} 
   		DQ.push_back(i-1);
   		while(!DQ.empty()&&i-DQ.front()>K){
    
    
   			DQ.pop_front();
   		}
   		ll tmp=sum[i]-sum[DQ.front()]; 
   		if(tmp>maxx){
    
    
   			maxx=tmp;
   			resl=DQ.front()+1;
   			resr=i;
   		}
   	}
   	cout<<maxx<<" "<<(resl-1+N)%N+1<<" "<<(resr-1+N)%N+1<<endl;
   }
   return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43311695/article/details/108734060