alan得到一块由个能量晶体构成的矿石,对于矿石中的每一个能量晶体,如果用化学物质刺激某一个能量晶体,就能使它释放能量。
它的能量释放强度与晶体本身的能量值以及能量晶体的位置有关。
为了方便研究,alan做了如下的定义。
能量集:一块矿石中的第个能量晶体到第个能量晶体(包含和,)构成的集合。
能量储存点:对于一块矿石中的能量晶体和,若有,则称是能量储存点。
能量释放点:在一个能量集中,若存在一个能量晶体,使得除它之外的所有能量晶体都是它的能量储存点,则称这个能量晶体是该能量集的能量释放点。
能量释放强度:对于一个能量集中的能量释放点来说,刺激这个能量晶体,该能量集中其余能量晶体会释放能量。该能量集的能量释放强度就等于该能量集中其余某个能量晶体的能量值与能量释放点的能量值的差的最大值。而第个能量晶体的能量释放强度则是所在的所有能量集的能量释放强度的最大值。
alan将给出矿石中能量晶体的个数,以及每个能量晶体的能量值,要求你求出每个能量晶体的能量释放强度。
第一行1个整数,表示矿石中能量晶体的个数。
第二行个整数,第个整数表示第个能量晶体的能量值。
仅包含一行个整数,第个整数表示第个能量晶体的能量释放强度。
5 3 2 1 2 3
0 1 2 1 0
题解:
在考场上我写的是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
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.
CH Round #45 能量释放,布布扣,bubuko.com
原文:http://www.cnblogs.com/zyfzyf/p/3895428.html