-
質問の意味
N個(N <= 10 ^ 5)の循環シーケンスが与えられた場合、合計が最大の連続サブシーケンスを見つけましょう。この連続サブシーケンスの長さはK以下です。 -
アイデアを
借りたこの大物のブログアイデアを
読んだ後、WAをノックしました。それから大物のコードを見ましたが、よくわかりませんでした。トラバースしました。なぜsum [i-1]が操作されるのですか?tmpを要求したときに、もう一度sum [i]を使用しました。後で理解したいと思いました。 。
iがトラバースされると、単調キューを使用して間隔[sum [i − k]、sum [i + 1 − k] ...、Sum [i − 1]] [sum [ik]、sum [i +1]が維持されます。 -k] ...、sum [i-1]][ s u m [ i−k ] 、s u m [ i+1−k ] 。。。、s u m [ i−1 ] ]これらのk個の数値の最小値。この最小値の添え字は、条件を満たす間隔の左端点であり、iは右端点です。この間隔のサイズはk以下です。極端な場合の合計[i−k]合計[ik]を考えてみましょう。s u m [ i−k ]的值gp、tmp =sum [i] − sum [i − k] sum [i] -sum [ik]s u m [ i ]−s u m [ i−k ]の値は、シーケンス内のk個の数値[i-k + 1、i]の合計です。したがって、キューを埋めようとするたびに、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;
}