BZOJ 3316: JC loves Mkk

来源:互联网 发布:阿里云服务器的优势 编辑:程序博客网 时间:2024/05/19 15:21

题目大意:

给定一个环,要求在这个环上截取长度为偶数且在[L,R]区间内的一段,要求平均值最大

分析

看到环果断倍增
看到平均值最大果断二分答案
看到长度[L,R]果断单调队列
对数组维护一个前缀和,对前缀和维护单调递增的单调队列
每扫过一个数sum[i],将sum[i-L]加入单调队列,再把距离i超过R的点删掉
长度为偶数?对奇数位置和偶数位置分别维护一个单调队列即可
每次找到大于0的子串之后记录一下分母再退出就行了

代码

#include <bits/stdc++.h>#define N 220006#define ll long longusing namespace std;long double sum[N];int n;int L,R;int mx;int num[N];int l[2],r[2];int Q[2][N];ll ans;int read(){    int x = 0, f = 1;    char ch = getchar();    while (ch < '0' || ch > '9')    {        if (ch == '-')            f = -1;        ch = getchar();    }    while (ch >= '0' && ch <= '9')    {        x = x * 10 + ch - '0';        ch = getchar();    }    return x * f;}ll gcd(ll x,ll y){    return x == 0 ? y : gcd(y % x, x);}bool check(long double y){    for (int i = 1; i <= n; i++)        sum[i] = sum[i - 1] + num[i] - y;    l[0] = 1; l[1] = 1;    r[0] = 0; r[1] = 0;    for (int i = L; i<= n; i++)    {        int w = i & 1, x = i - L;        while (r[w] >= l[w] && sum[x] < sum[Q[w][r[w]]])            r[w]--;        while (r[w] >= l[w] && Q[w][l[w]] < i - R)            l[w]++;        Q[w][++r[w]] = x;        if (sum[i] - sum[Q[w][l[w]]] >= 0)            return ans = i - Q[w][l[w]];    }    return 0;}int main(){    n = read(); L = read(); R = read();    for (int i = 1; i <= n; i++)        num[i] = read(), mx = max(mx,num[i]);    for (int i = 1; i <= n; i++)        num[n + i] = num[i];    if (L & 1)        L++;    if (R & 1)        R--;    n *= 2;    long double l = 0, r = mx;    while (r - l > 1e-7)    {        long double mid = (l + r) / 2;        if (check(mid))            l = mid;        else r = mid;    }    long double tmp = (l + r) / 2;    ll w = (ll)(ans * tmp + 0.5);    ll Gcd = gcd(w,ans);    w /= Gcd; ans /= Gcd;    if (ans == 1)        cout<<w<<endl;    else cout<<w<<'/'<<ans<<endl;}
0 0