洛谷P1419 尋找段落(二分+單調佇列)
阿新 • • 發佈:2018-12-12
題解:題中需要我們去求一個最大的長度在之間的連續子序列平均值。 即 由此發現答案單調,因此可以用二分來做,我們稍作轉換,發現如果滿足,我們就可以繼續增大,否則就減小。但是為了求解方便,我們發現可以將式子再簡化一下,轉換成求。因此我們需要求的是區間內的最大子段和,用單調佇列去求就好了。
程式碼
#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
LL n,x,S,T,sum[100010],a[100010];
bool love(LL x)
{
memset(sum,0,sizeof sum);
for(int i = 1; i <= n; ++i)
sum[i] = sum[i - 1] + a[i] - x;
deque<LL> dq;
for(int i = 1, s = S; s <= n; ++i, ++s){
while(!dq.empty() && sum[dq.back()] > sum[i - 1])
dq.pop_back();
while(!dq.empty() && dq.front() + T < s) //控制子段長度
dq.pop_front();
dq.push_back (i - 1);
if(sum[s] - sum[dq.front()] >= 0) return 1;
}
return 0;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.in","r",stdin);
#endif
cin>>n>>S>>T;
for(int i = 1; i <= n; ++i){
cin>>a[i];
a[i] *= 10000;
}
int L = -1e9, R = 1e9;
while(L + 1 < R){
LL mid = (L + R)>>1;
if(love(mid))
L = mid;
else
R = mid;
}
printf("%.3f\n",1.0*L/10000);
return 0;
}