UVA1451 Average

链接

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4197

题解

这题就是给你若干个点 ( i , s i ) ,要你找出连线斜率最大的一对点
当然,可以维护一个下凸壳,然后对于每个点 O ( s i z e ) 扫描凸壳上的点求得最值,其中 s i z e 是凸壳上点的个数
这个题的性质比较好,凸壳上的点很少,所以能 A
另外,这个题具有决策单调性,可以从上一个点的决策往后扫描,能够加快速度
但我还是觉得这样太玄学,如果 s i z e 足够大,就能卡掉这个算法,谁能想出一组数据卡掉这个算法?请在评论区发表意见

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <cmath>
#define maxn 100010
#define eps 1e-8
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
int s[maxn], n, w[maxn], L, tot;
double ans;
struct point
{
    double x, y;
}pt[maxn], hull[maxn], left, right;
double k(point& a, point& b){return (b.y-a.y)/(b.x-a.x);}
int read(int x=0)
{
    char c, f=1;
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-1;
    for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-48;
    return f*x;
}
int readd()
{
    char c;
    for(c=getchar();!isdigit(c);c=getchar());
    return c;
}
void init()
{
    int i;
    n=read(), L=read();
    for(i=1;i<=n;i++)s[i]=readd()+s[i-1];
    for(i=0;i<=n;i++)pt[i]=(point){i,s[i]};
    tot=0;
}
void work()
{
    int i, j;
    double t;
    point now, best;
    ans=-1;
    for(i=L;i<=n;i++)
    {
        now=pt[i-L];
        for(;tot>=2 and k(now,hull[tot])<k(hull[tot],hull[tot-1]);tot--);
        hull[++tot]=now;
        now=pt[i];
        t=-1;
        for(j=1;j<=tot;j++)if(k(hull[j],now)>t-eps)best=hull[j], t=k(now,hull[j]);
        if(t>ans)ans=t, left=best, right=now;
        else if(fabs(t-ans)<eps)
        {
            if(right.x-left.x > now.x-best.x)left=best, right=now;
        }
    }
    printf("%.0lf %.0lf\n",left.x+1,right.x);
}
int main()
{
    int T=read();
    while(T--)
    {
        init();
        work();
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/FSAHFGSADHSAKNDAS/article/details/81280106