链接
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4197
题解
这题就是给你若干个点
,要你找出连线斜率最大的一对点
当然,可以维护一个下凸壳,然后对于每个点
扫描凸壳上的点求得最值,其中
是凸壳上点的个数
这个题的性质比较好,凸壳上的点很少,所以能
掉
另外,这个题具有决策单调性,可以从上一个点的决策往后扫描,能够加快速度
但我还是觉得这样太玄学,如果
足够大,就能卡掉这个算法,谁能想出一组数据卡掉这个算法?请在评论区发表意见
代码
#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;
}