uva 1451 平均值

题目大意:

一个01串,求一段长度至少为L的区间使这个区间的平均值最大

思路:

因为是一个01串,所以我们可以把串内的点都当做点来处理

每个点的横坐标为它的位置,而纵坐标则为它的前缀和

这样这个串就变为了一个阶梯式的图像

如果点p在线段AB或BC上,取点i

 

如果点p在点C上方,取点k

所以点j并没有啥用,我们可以把它删掉了

我们可以枚举每个结尾点

根据上面的结论我们可以删除距离结尾点l外所有上凸点留下一个凸包

对于这个我们可以使用单调队列来实现

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<vector>
#define inf 2147483611
#define ll long long
#define MAXN 101010
#define MOD 
using namespace std;
inline int read()
{
    int x=0,f=1;
    char ch;ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
} 
int n,l,T;
int q[MAXN],s[MAXN],head,tail;
char x;
int cmp(int x1,int x2,int x3,int x4) {return (s[x2]-s[x1])*(x4-x3)-(s[x4]-s[x3])*(x2-x1);}
int main()
{
    T=read();
    while(T--)
    {
        head=tail=0;
        n=read(),l=read();
        for(int i=1;i<=n;i++)
        {
            x=getchar();
            s[i]=s[i-1]+x-'0';
        }
        int al=0,ar=l;
        for(int i=l;i<=n;i++)
        {
            while(head<tail-1&&cmp(i-l,q[tail-1],i-l,q[tail-2])<0) tail--;//当前队尾不需要 
            q[tail++]=i-l;
            while(head<tail-1&&cmp(q[head+1],i,q[head],i)>=0) head++;//当前队首不需要 
            if(cmp(q[head],i,al,ar)>0||(cmp(q[head],i,al,ar)==0&&(i-q[head]<ar-al))) al=q[head],ar=i;//斜率优于答案或斜率相同长度更短 
        }
        printf("%d %d\n",al+1,ar);
    }
}
View Code

 

posted @ 2017-10-03 15:19  jack_yyc  阅读(272)  评论(0编辑  收藏  举报