GDOI2005 河床 题解

Description

  地理学家们经常要对一段河流进行测量分析。他们从上游开始向下游方向等距离地选择n(<=30000)个点测量水位深度。得到一组数据d1,d2,…,dn,回到实验室后数据分析员根据需要对数据进行分析,发掘隐藏在数据背后的规律。最近,乌龙博士发现某种水文现象与河床地势有关,于是他指示他手下的分析员要找出一段河流中最大高低起伏差不超过k(k<=100)的最长一段。这看似一个复杂的问题,由于任务紧急,分析员来求助于你,并告诉你博士的所有数据都精确到个位。

Input

  输入文件有两行:第一行是整数n,k,分别表示测量点的个数和博士要求的最大水深差(也就是河床地势差)。第二行有n个整数,表示从上游开始依次得到的水位深度 di(1<=i<=n,0<=di<=32767)。

Output

  输出文件只有一行,是整数m,表示最长一段起伏不超过k的河流长度,用测量点个数表示。

Sample Input

6 2
5 3 2 2 4 5

Sample Output

4

Data Constraint

Hint

  提示:从第二个测量点到第五个测量点之间的那段:3 2 2 4,他们起伏最大时4-2=2。

题解

一眼DP的题,而且还是单调队列。
但是姿势水平不够,DP解法留坑。
ST表维护最大值和最小值,然后二分答案,O(n)判断,总复杂度O(nlogn)
据说有暴力+去重+break可以跑得比我快qwq

var n,k,i,j,l,r,mid,ans:longint;
lg,a:array[0..100000]of longint;
f1,f2,f3:array[0..100000,0..20]of longint;
function max(x,y:longint):longint;
begin
  if x>y then exit(x) else exit(y);
end;
function min(x,y:longint):longint;
begin
  if x>y then exit(y) else exit(x);
end;
begin
  readln(n,k);
  for i:=1 to n do read(a[i]);
  readln;
  for i:=1 to n-1 do begin
    f1[i,0]:=i+1;
    f2[i,0]:=max(a[i+1],a[i]);
    f3[i,0]:=min(a[i+1],a[i]);
  end;
  for i:=1 to 18 do begin
    for j:=1 to n do begin
      f1[j,i]:=f1[f1[j,i-1],i-1];
      f2[j,i]:=max(f2[j,i-1],f2[f1[j,i-1],i-1]);
      f3[j,i]:=min(f3[j,i-1],f3[f1[j,i-1],i-1]);
    end;
  end;
  for i:=2 to n do lg[i]:=lg[i div 2]+1;
  l:=1;
  r:=n;
  while l<=r do begin
    mid:=(l+r)div 2;
    for i:=1 to n-mid do begin
      if max(f2[i,lg[mid]],f2[i+mid-(1 shl lg[mid]),lg[mid]])-min(f3[i,lg[mid]],f3[i+mid-(1 shl lg[mid]),lg[mid]])<=k then begin
        ans:=mid+1;
        break;
      end;
    end;
    if ans=mid+1 then l:=mid+1 else r:=mid-1;
  end;
  if ans=0 then ans:=1;
  writeln(ans);
end.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值