原题意思是求一个不超过 k 的连续序列的和的最大值。
枚举连续序列的起点 i, 然后在 [i, i+k] 区间找一个最大值,更新答案。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define max(a,b) ( (a)> (b)? (a): (b) )
#define min(a,b) ( (a)< (b)? (a): (b) )
int const N= 200010;
int dat[N], sum[N];
int n, nn, k;
struct Node{
int Max, pos;
Node(){}
Node( int a, int b ): Max(a), pos(b) {}
}tb[N<<2];
inline bool operator>( Node a, Node b ){
if( a.Max== b.Max ) return a.pos< b.pos;
return a.Max> b.Max; }
void build( int L, int R, int rt ){
if( L== R ){
tb[rt]= Node( sum[L], L );
return ;}
int mid= (L+ R)>>1;
build( L, mid, rt<<1 );
build( mid+ 1, R, rt<<1|1 );
tb[rt]= max( tb[rt<<1], tb[rt<<1|1] );
}
Node query( int a, int b, int L, int R, int rt ){
if( a== L && b== R ) return tb[rt];
int mid= (L+ R)>>1;
if( b<= mid ) return query( a, b, L, mid, rt<<1 );
else if( a> mid ) return query( a, b, mid+ 1, R, rt<<1|1 );
else{
Node x= query( a, mid, L, mid, rt<<1 );
Node y= query( mid+ 1, b, mid+ 1, R, rt<<1|1 );
return max(x,y);
}
}
inline int read(){
char ch;
int d, flag= 1;
while( ch= getchar(), ch== ' ' || ch== '\n' );
if( ch== '-' ) { flag= -1; d= 0; }
else{ d= ch- '0'; }
while( ch= getchar(), ch>= '0' && ch<= '9' )
d= d* 10+ ch- '0';
return d* flag;
}
int main(){
int test;
scanf("%d",&test );
while( test-- ){
scanf("%d%d",&n,&k );
for( int i= 1; i<= n; ++i ){
dat[i]= read();
dat[i+ n]= dat[i];
}
sum[0]= 0; nn= n<<1;
for( int i= 1; i<= nn; ++i )
sum[i]= sum[i-1]+ dat[i];
build( 1, nn, 1 );
int ans= -0x7fffffff, posx= 0, posy= 0;
for( int i= 0; i<= n; ++i ){
int t= min( i+ k, nn );
Node tmp= query( i+ 1, t, 1, nn, 1 );
if( tmp.Max- sum[i]> ans ){
ans= tmp.Max- sum[i];
posx= i+ 1;
posy= tmp.pos;
}
}
printf("%d %d ", ans, posx );
if( posy> n ) printf("%d\n", posy- n );
else printf("%d\n", posy );
}
return 0;
}