NKOJ 平均值【斜率優化】
阿新 • • 發佈:2018-12-12
問題描述
給定一個長度為n的01串,選一個長度至少為L的連續子串,使得子串中數字的平均值最大。 如果有多解,子串長度應儘量小;如果仍有多解,起點編號儘量小。 序列中字元編號1到n,1<=n<=300000, 1<=L<=3000. 例如:對於長度為17的序列00101011011011010,如果L=7,最大平均值為6/8(子序列[7,14]);如果L=5,子序列[7,11]平均值最大,為4/5
輸入格式
第一行,兩個整數n和L 第二行,一個長度為n的01序列
輸出格式
一行,兩個整數,表示所選子序列的起點和終點
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define ll long long #define rep(i,x,y) for(ll i=(x);i<=(y);i++) #define repl(i,x,y) for(ll i=(x);i<(y);i++) #define repd(i,x,y) for(ll i=(x);i>=(y);i--) using namespace std; const ll N=3e5+5; const ll Inf=1e18; char ch[N]; ll n,m,l,r,q[N],sum[N]; inline ll read() { ll x=0;char ch=getchar();bool f=0; while(ch>'9'||ch<'0'){if(ch=='-')f=1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return f?-x:x; } ll check(ll x1,ll x2,ll x3,ll x4) { return (sum[x2]-sum[x1-1])*(x4-(x3-1))-(sum[x4]-sum[x3-1])*(x2-(x1-1)); } int main() { n=read(),m=read(); scanf("%s",ch+1); rep(i,1,n) sum[i]=sum[i-1]+ch[i]-'0'; ll ans1=1,ans2=m; rep(i,m,n) { while(r>l+1&&check(q[r-2],i-m,q[r-1],i-m)>=0) r--; q[r++]=i-m+1; while(r>l+1&&check(q[l],i,q[l+1],i)<=0) l++; ll slope=check(q[l],i,ans1,ans2); if(slope>0) ans1=q[l],ans2=i; } printf("%lld %lld\n",ans1,ans2); return 0; }