某套NOIP模拟

传送门

http://218.28.19.228/cogs/problem/problem.php?pid=2064
http://218.28.19.228/cogs/problem/problem.php?pid=2065
http://218.28.19.228/cogs/problem/problem.php?pid=2066

T1 爬山

题目大意

给定初始位置,能花费的时间,末了位置,以及每次移动(向上或向下)的最大距离,询问最高能达到多少

题解

我们画画图想一下,其实就是努力向上爬再努力向下爬到达末了位置,时间在规定以内就好,所以我们二分答案就可以啦
ans,ansad+ansbd<=n
向上取整可以有不讨论的技巧,比如说 ansad ,就可以写成((ans-a-1)div d)+1
注意二分不要被卡住!
注意二分不要被卡住!
注意二分不要被卡住!
二分真的真的真的真的真的是很容易挂的东西!!!

var
 tt,l,r,mid,n,d,a,b:int64;
function check(ans:int64):longint;
begin
 tt:=(ans-a-1)div d; inc(tt);
 if (n-tt)*d+b>=ans
 then exit(1)
 else exit(0);
end;

begin
 assign(input,'mountain.in'); assign(output,'mountain.out'); reset(input); rewrite(output);
 readln(n,d,a,b); dec(n);
 l:=a; r:=d*n+a;
 while l<r do
  begin
   mid:=(l+r) div 2;
   if check(mid)=1
   then l:=mid
   else r:=mid-1;
   if l+1=r then break;
  end;
 if check(r)=1 then l:=r;
 writeln(l);
 close(input); close(output);
end.

T2 学数数

题目大意

n,n(n+1)2,,q//k

题解

这题其实很好想的,但是考试时候我一直写到结束都没处理好二分讨论,没错,又是二分!!!
好吧,我们先说说怎么做
我们发现,取出的数也只是那n个数中的数,只是数的个数有区别,所以我们想办法处理出每个数的个数,其实就相当于每个数的贡献,每个数往两边扩展直到比它大的数出现,就像最大全0子矩阵中的一行一样,我们用单调栈轻松处理,但是我们从数据范围的提示中发现,数中有重复,也就是扩展的时候有相等的,我在考试时想到的是先离散化,处理完再离散化回来,其实不用没有重复的时候是x[k]< x[i]< x[j],重复就把把其中一边带上等号即可了….因为相同的数在同一区间里效果是一样的,和离散化的想法一样就是规定相同的哪个大,一边取等就是直接用它们的数组下标来限定,
查询时二分就好,到底怎么二分查找其实我还不太清楚,因为我不觉得二分讨论会讨论到我写的程度,等我再求教神犇之后再写吧

const
 maxn=100050;
var
 t,l,r,x,z:array[0..maxn]of longint;
 sum,y,ans:array[0..maxn]of int64;
 i,j,k:longint;
 n,q,len,tt,ll,rr,mid,pp:longint;
 ch:char;
procedure sort(l,r:longint);
var i,j,a,b:longint; c:int64;
begin
 i:=l; j:=r; a:=x[(l+r) div 2];
 repeat
  while x[i]<a do inc(i);
  while a<x[j] do dec(j);
  if not(i>j) then
   begin
    b:=x[i]; x[i]:=x[j]; x[j]:=b;
    c:=y[i]; y[i]:=y[j]; y[j]:=c;
    inc(i); dec(j);
   end;
 until i>j;
 if l<j then sort(l,j);
 if i<r then sort(i,r);
end;

begin
 assign(input,'jxthree.in'); assign(output,'jxthree.out'); reset(input); rewrite(output);
 readln(n,q);
 for i:=1 to n do
  read(x[i]);
 readln;
 t[1]:=1; l[1]:=1; len:=1; t[0]:=0; x[0]:=maxlongint;
 for i:=2 to n do
  begin
   tt:=0;
   for j:=len downto 0 do
    if x[i]<x[t[j]]
    then begin l[i]:=i-t[j]; tt:=j; break; end
    else r[t[j]]:=i-t[j];
   len:=tt+1; t[len]:=i;
  end;
 for i:=1 to len do
  r[t[i]]:=n+1-t[i];
 for i:=1 to n do
  y[i]:=int64(l[i])*int64(r[i]);
 sort(1,n); len:=0; x[0]:=-1;
 for i:=1 to n do
  if x[i]<>x[i-1] then begin inc(len); z[len]:=x[i]; end;
 tt:=0;
 for i:=1 to n do
  begin
   if x[i]<>x[i-1] then inc(tt);
   inc(ans[tt],y[i]);
  end;
 sum[0]:=0;
 for i:=1 to n do
  sum[i]:=sum[i-1]+ans[i];
 for i:=1 to q do
  begin
   readln(ch,k); pp:=0;
   if k>z[len] then begin
    case ch of
    '<':writeln(sum[len]);
    '=':writeln(0);
    '>':writeln(0);
    end;
    continue;
   end;
   ll:=1; rr:=len; j:=0;
   while ll<=rr do
    begin
     mid:=(ll+rr)>>1;
     if z[mid]=k then begin
      case ch of
      '<':writeln(sum[mid-1]);
      '=':writeln(ans[mid]);
      '>':writeln(sum[len]-sum[mid]);
      end;
      j:=1; break;
     end;
     if z[mid]<k
     then ll:=mid
     else rr:=mid;
     inc(pp); if pp=20 then break;
    end;
   if j=1 then continue;
   if (z[ll]=k)or(z[rr]=k) then begin
    if z[ll]=k then mid:=ll;
    if z[rr]=k then mid:=rr;
    case ch of
    '<':writeln(sum[mid-1]);
    '=':writeln(ans[mid]);
    '>':writeln(sum[len]-sum[mid]);
    end;
    continue;
   end;
   if k<z[ll]
   then dec(ll)
   else if k>z[rr] then inc(ll);
   case ch of
   '<':writeln(sum[ll]);
   '=':writeln(0);
   '>':writeln(sum[len]-sum[ll]);
   end;
  end;
 close(input); close(output);
end.

T3 七十和十七

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值