bzoj 1067: [SCOI2007]降雨量 RMQ+讨论

来源:互联网 发布:重庆网络推广团队 编辑:程序博客网 时间:2024/06/04 19:52

分析:先用RMQ的ST算法求出区间最大值,然后进行分类讨论:

设u为不大于Y的最大年份的下标,v为不小于X的最小年份的下标

如果X、Y降雨量都为已知切r[v]>r[u]则为false

如果X、Y都为不知则maybe

若至少知道其中一个且区间最大值不小于min(r[u],r[v])则false

若有空缺或X、Y至少一个为不知则maybe

最后true

注意X=Y和X或Y<0或X<Y则要特判


代码:

const  maxn=50100;var  n:longint;  mi:array[0..20] of longint;  y,a,s:array[0..maxn] of longint;  f:array[1..maxn,0..20] of longint;procedure init;var  i:longint;begin  readln(n);  for i:=1 to n do    readln(y[i],a[i]);  y[0]:=-maxlongint;  y[n+1]:=maxlongint;  for i:=1 to n-1 do    if y[i+1]-y[i]>1 then s[i]:=1;  for i:=1 to n do    s[i]:=s[i-1]+s[i];end;function min(x,y:longint):longint;begin  if x<y then exit(x)         else exit(y);end;function max(x,y:longint):longint;begin  if x>y then exit(x)         else exit(y);end;procedure st;var  i,j,maxl:longint;begin  for i:=1 to n do    f[i,0]:=a[i];  maxl:=trunc(ln(n)/ln(2));  mi[0]:=1;  for i:=1 to maxl do    mi[i]:=mi[i-1]*2;  for j:=1 to trunc(ln(n)/ln(2)) do    for i:=1 to n-mi[j]+1 do      f[i,j]:=max(f[i,j-1],f[i+mi[j-1],j-1]);end;function ef1(x:longint):longint;var  l,r,mid:longint;begin  l:=1;  r:=n;  while l<=r do  begin    mid:=(l+r) div 2;    if y[mid]<=x      then l:=mid+1      else r:=mid-1;  end;  ef1:=l-1;end;function ef2(x:longint):longint;var  l,r,mid:longint;begin  l:=1;  r:=n;  while l<=r do  begin    mid:=(l+r) div 2;    if y[mid]>=x      then r:=mid-1      else l:=mid+1;  end;  ef2:=r+1;end;function check(l,r,minr:longint):boolean;var  maxl,maxr,i:longint;begin  if l>r then exit(true);  maxl:=trunc(ln(r-l+1)/ln(2));  maxr:=0;  for i:=maxl downto 0 do    if l+mi[i]-1<=r then    begin      maxr:=max(maxr,f[l,i]);      l:=l+mi[i];    end;  if maxr<minr    then exit(true)    else exit(false);end;procedure main;var  q,x,w,u,v,minr,i:longint;begin  st;  readln(q);  for i:=1 to q do  begin    readln(x,w);    u:=ef1(x);    v:=ef2(w);    if (x=y[u])and(w=y[v])and(a[v]>a[u])or(x>w) then    begin      writeln('false');      continue;    end;    if w=x then    begin      writeln('true');      continue;    end;    minr:=maxlongint;    if x=y[u] then minr:=min(minr,a[u]);    if w=y[v] then minr:=min(minr,a[v]);    if check(u+1,v-1,minr)      then if (x=y[u])and(w=y[v])and(s[v-1]-s[u-1]=0)             then writeln('true')             else writeln('maybe')      else writeln('false');  end;end;begin  init;  main;end.


0 0
原创粉丝点击