zoukankan      html  css  js  c++  java
  • CH Round #45 能量释放

    能量释放 CH Round #45 - alan有一些陷阱 III

    题目描述

        alan得到一块由$N$个能量晶体构成的矿石,对于矿石中的每一个能量晶体,如果用化学物质刺激某一个能量晶体,就能使它释放能量。

        它的能量释放强度与晶体本身的能量值$A_{i}$以及能量晶体的位置$i$有关。

        为了方便研究,alan做了如下的定义。

        $ullet$能量集:一块矿石中的第$i$个能量晶体到第$j$个能量晶体(包含$i$$j$$1leq i leq j leq N$)构成的集合。

        $ullet$能量储存点:对于一块矿石中的能量晶体$i$$j(i 
eq j)$,若有$A_{j} geq A_{i}$,则称$j$$i$能量储存点。

        $ullet$能量释放点:在一个能量集中,若存在一个能量晶体,使得除它之外的所有能量晶体都是它的能量储存点,则称这个能量晶体是该能量集的能量释放点。

        $ullet$能量释放强度:对于一个能量集中的能量释放点来说,刺激这个能量晶体,该能量集中其余能量晶体会释放能量。该能量集的能量释放强度就等于该能量集中其余某个能量晶体的能量值与能量释放点的能量值的差的最大值。而第$i$个能量晶体的能量释放强度则是$i$所在的所有能量集的能量释放强度的最大值。

        alan将给出矿石中能量晶体的个数$N$,以及每个能量晶体的能量值$A_{i}$,要求你求出每个能量晶体的能量释放强度。

    输入格式

        第一行1个整数$N$,表示矿石中能量晶体的个数。

        第二行$N$个整数,第$i$个整数表示第$i$个能量晶体的能量值$A_{i}$

    输出格式

        仅包含一行$N$个整数,第$i$个整数表示第$i$个能量晶体的能量释放强度。

    样例输入

    5
    3 2 1 2 3

    样例输出

    0 1 2 1 0

    数据范围与约定

      

    • 对于20%的数据:$1 leq N leq 1000$
    • 对于60%的数据:$1 leq N leq 300000$
    • 对于100%的数据:$1 leq N leq 2000000,0 leq |A_{i}| leq 2 	imes 10^{9}$
    • 温馨提醒:本题数据量较大,请尽量使用输入输出优化。

    题解:
    在考场上我写的是O(n)的单调队列(其实也相当于是单调栈。。。)+O(nlogn)的rmq
    自己为能AC,结果只有一半
    后来才知道如果数据规模达到百万以上,就一定得用O(n)的算法了,我还是太年轻啊。。。
    今天准备做NOI2005瑰丽的华尔兹时,又用到了单调队列,忽然对这题有了想法,就又来做

    这次我的算法,均摊应该是O(n)的吧。。。我想是这样。。。

    其实考虑到a[i]左边的元素如果比a[j]小的话,那 j 管辖的范围 i 也也一定可以,(j 的初始值为 i-1)

    所以我们直接跳到 j 管辖的范围的左边即可,即 j=l[j]-1 同时用 它来更新f[i]

    最后跳不动的时候,j+1就是 l[i]

    右边类似。。。

    不知到复杂度是多少?怎么估计?求大神指教

    自测稍有超时,后几个点都是1.2s左右的样子

    代码:

    1.考场 跑完所有数据需要 22s

     1 var  i,j,n,h,t:longint;
     2      f:array[0..2000000+10,0..20] of longint;
     3      a,q,l,r:array[0..2000000+10] of longint;
     4   procedure init;
     5    begin
     6      readln(n);
     7      for i:=1 to n do read(a[i]);
     8    end;
     9  procedure queue;
    10    begin
    11      a[0]:=-2100000000;a[n+1]:=a[0];
    12      fillchar(q,sizeof(q),0);
    13      h:=0;t:=0;
    14      for i:=1 to n+1 do
    15       begin
    16         while (h<t) and (a[i]<a[q[t]]) do
    17            begin
    18              r[q[t]]:=i-1;
    19              dec(t);
    20            end;
    21         inc(t);q[t]:=i;
    22       end;
    23      fillchar(q,sizeof(q),0);
    24      h:=0;t:=0;
    25      for i:=n downto 0 do
    26        begin
    27          while (h<t) and (a[i]<a[q[t]]) do
    28            begin
    29              l[q[t]]:=i+1;
    30              dec(t);
    31            end;
    32          inc(t);q[t]:=i;
    33        end;
    34      end;
    35 function max(x,y:longint):longint;
    36  begin
    37    if x>y then exit(x) else exit(y);
    38  end;
    39 
    40 procedure rmq;
    41   begin
    42     fillchar(f,sizeof(f),127);
    43     for i:=1 to n do f[i,0]:=a[i];
    44     for i:=1 to 22 do
    45      begin
    46        if (1<<i)>n then break;
    47        for j:=1 to n-(1<<i)+1 do
    48         f[j,i]:=max(f[j,i-1],f[j+1<<(i-1),i-1]);
    49      end;
    50   end;
    51 function query(x,y:longint):int64;
    52  var k:longint;
    53  begin
    54   k:=trunc(ln(y-x+1.0)/ln(2.0));
    55   exit(max(f[x,k],f[y-(1<<k)+1,k]));
    56  end;
    57 
    58 procedure main;
    59   begin
    60     queue;
    61     rmq;
    62   //  for i:=1 to n do writeln(l[i],' ',r[i]);
    63     for i:=1 to n do
    64       write(query(l[i],r[i])-a[i],' ');
    65   end;
    66 begin
    67   assign(input,'input.txt');assign(output,'output.txt');
    68   reset(input);rewrite(output);
    69   init;
    70   main;
    71   close(input);close(output);
    72 end.
    73                                    
    View Code

    2.20140806 跑完所有数据需要 6s

     1 {$inline on}
     2 const maxn=2000000+100;
     3 var l,r,a,f:array[0..maxn] of longint;
     4     i,n,j:longint;
     5     function max(x,y:longint):longint;inline;
     6      begin
     7        if x>y then exit(x) else exit(y);
     8      end;
     9 
    10 procedure init;
    11  begin
    12    readln(n);
    13    for i:=1 to n do begin read(a[i]);f[i]:=a[i];end;
    14  end;
    15 procedure main;
    16  begin
    17    a[0]:=-maxlongint;a[n+1]:=-maxlongint;
    18    l[1]:=1;
    19    for i:=2 to n do
    20     begin
    21     j:=i-1;
    22     while a[i]<=a[j] do
    23      begin
    24      if f[j]>f[i] then f[i]:=f[j];
    25      j:=l[j]-1;
    26      end;
    27     l[i]:=j+1;
    28     end;
    29    r[n]:=n;
    30    for i:=n-1 downto 1 do
    31     begin
    32     j:=i+1;
    33     while a[i]<=a[j] do
    34      begin
    35      if f[j]>f[i] then f[i]:=f[j];
    36      j:=r[j]+1;
    37      end;
    38     r[i]:=j-1;
    39     end;
    40    for i:=1 to n-1 do write(f[i]-a[i],' ');writeln(f[n]-a[n]);
    41   end;
    42 begin
    43   assign(input,'input.txt');assign(output,'output.txt');
    44   reset(input);rewrite(output);
    45   init;
    46   main;
    47   close(input);close(output);
    48 end.    
    View Code
  • 相关阅读:
    从0开始学Swift笔记整理(二)
    从0开始学Swift笔记整理(一)
    JAVA反射机制
    Spring基础知识汇总
    关于类和对象的进一步讨论 C++
    C++ 共用体 枚举类型 所有
    自定义数据类型 C++ 结构体类型 共同体类型 枚举类型 类类型{}
    C++ 指针 引用 变量引用
    函数和指针 C++
    C++字符串与指针 所有的内容也就这么多了。
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/3895428.html
Copyright © 2011-2022 走看看