UVALive 4726 Average(数形结合)

来源:互联网 发布:托业模拟考试软件 编辑:程序博客网 时间:2024/06/05 08:16

题意:给出一个01串,选一个长度至少为L的子序列使得子序列数字的平均值最大。

思路:为了这题又看了个论文……是04年国家集训队 周源的《浅谈数形结合思想在信息学竞赛中的应用》,感觉这样不行啊,有时间要好好看看这些论文,不能碰到一道题再去看。其实这个平均值在坐标中画出来就相当于斜率,从而转化成寻找两点之间最大斜率的问题,维护一个下凹的图形序列就行了。感觉我写的有些丑啊,最后调了半天发现初始化错了Orz,不能再sb了


代码:

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<set>#include<stack>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-9#define pi acos(-1.0)using namespace std;typedef long long ll;const int maxn=100000+10;struct Point{    double x,y;    Point (){};    Point (double xx,double yy) {x=xx;y=yy;}};Point p[maxn];typedef Point Vector;double Cross(Vector a,Vector b) {return a.x*b.y-a.y*b.x;}Vector operator -(Point a,Point b) {return Vector(a.x-b.x,a.y-b.y);}double calk(Point a,Point b) {  return (b.y-a.y)/(b.x-a.x);}int dcmp(double x){    if(fabs(x)==0) return 0;    return x>0?1:-1;}char str[maxn];int n,L,maxl,maxr;double maxv;Point sp[maxn];void solve(){    int m=0;    sp[m++]=p[0];    int s=0,tmp;    double k,tmp2;    bool flag;    for(int i=L;i<=n;++i)    {        flag=false;        if(s<m&&sp[s].x<=i-L)        {            k=calk(sp[s],p[i]);            while(s+1<m)            {                tmp2=calk(sp[s+1],p[i]);                if(dcmp(k-tmp2)<=0) {s++;k=tmp2;}                else break;            }            tmp=dcmp(k-maxv);            if(tmp>=0)            {                maxv=k;                if(tmp>0||(tmp==0&&maxr-maxl+1>(int)(p[i].x-sp[s].x+eps)))                {maxl=sp[s].x+1+eps;maxr=p[i].x+eps;}            }        }        while(m>s+1&&Cross(sp[m-1]-sp[m-2],p[i-L+1]-sp[m-1])<0) m--;        sp[m++]=p[i-L+1];    }}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int t;    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&n,&L);        scanf("%s",str);        int sum=0;        p[0]=Point(0,0);        for(int i=0;i<n;++i)        {            sum+=(str[i]-'0');            p[i+1]=Point(i+1,sum);        }        maxv=0;        if(L==1)        {            if(sum==0) {maxl=maxr=1;}            else            {                for(int i=0;i<n;++i)                    if(str[i]=='1') {maxl=maxr=i+1;break;}            }        }        else solve();        printf("%d %d\n",maxl,maxr);    }    return 0;}


0 0
原创粉丝点击