• 【以前的空间】 单调队列系列


    https://www.vijos.org/p/1580

      这道题可以很简单地写出一个二维循环的解法,就是对于每个节点i,往前扫比这个节点高度大的节点,看能扫到哪,往后扫对这个节点高度大的节点,看能扫到哪。这样对于n≤100,000的数据会爆。于是我们可以想到,如果我们是这样处理:即对于节点i,我们并不是找他能扫到哪,而是节点i是哪个节点的最后或者最左的节点。然后就用到神奇的单调队列:首先对于节点i,将i之前比它高的点j全出队,因为此时j不可能扫过i(a[j]>a[i]),然后j能扫到最右的距离就是i了;然后再将此点入队。  一个小东西就是把n+1点的高度弄完0,这样所有点就都比n+1大了……

    var
     s,q,s2,a:array[0..10]of int64;
     i,j,k,l,r,n:longint;
     ans:int64;
    
    begin
     while not eof do begin
       fillchar(s,sizeof(s),0);
       fillchar(q,sizeof(q),0);
       read(n);
       for i:=1 to n do
         read(a[i]);
       readln;
       l:=1;
       r:=0;
       for i:=1 to n+1 do begin
         while (l<=r) and (a[i]<a[q[r]]) do begin
           s[q[r]]:=i;
           dec(r);
         end;
         inc(r);
         q[r]:=i;
       end;
       l:=1;
       r:=0;
       fillchar(q,sizeof(q),0);
       for i:=n downto 0 do begin
         while (l<=r) and (a[i]<a[q[r]]) do begin
           s2[q[r]]:=i;
           dec(r);
         end;
         inc(r);
         q[r]:=i;
       end;
       ans:=0;
       for i:=1 to n do
         if (s[i]-s2[i]-1)*a[i]>ans then
           ans:=(s[i]-s2[i]-1)*a[i];
       writeln(ans);
     end;
     writeln('0');
     readln;
    end.
    View Code

    vijos 1091

    var
      a,b,c,f,ff,s:array[0..1000000]of longint;
      i,j,k,l,n,m,r:longint;
      flag:boolean;begin
      readln(n,l);
      readln(b[n],a[1]);
      for i:=2 to n do begin
        readln(b[i-1],a[i]);
        dec(l,b[i-1]);
      end;
      b[n]:=l;
      for i:=1 to n do begin
        c[i]:=a[i]-b[i];
        c[i+n]:=c[i];
      end;
      s[0]:=0;
      for i:=1 to n+n do
        s[i]:=s[i-1]+c[i];
      l:=1;
      r:=0;
      flag:=false;
      for i:=1 to n do begin
        while (l<=r) and (s[i]<ff[r]) do dec(r);
        inc(r);
        ff[r]:=s[i];
        f[r]:=i;
      end;
      for i:=n to n+n-1 do begin
        while (f[l]<=i-n) and (l<=r) do inc(l);
        while (l<=r) and (s[i]<ff[r]) do dec(r);
        inc(r);
        ff[r]:=s[i];
        f[r]:=i;
        if s[i-n]<=ff[l] then begin
          flag:=true;
          write(i-n+1,' ');
        end;
      end;
      if flag=false then begin
        writeln(-1);
      end;end.
    View Code

    转载于:https://www.cnblogs.com/Macaulish/p/6492043.html

  • 相关阅读:
    桌面图标背景透明
    如何做好一个中小型企业计算机网络管理员
    打开IE8总是提示欢迎使用?怎样使它不提示?
    js 操作select和option,添加select列
    bios 被加密,怎么进入bios
    Foxmail自动收取新邮件
    代码片段
    提高生活幸福感的13个方法
    水晶报表的真实体验
    游标替代
  • 原文地址:https://www.cnblogs.com/twodog/p/12141152.html
Copyright © 2020-2023  润新知