標籤:style blog http color 使用 os io 資料
能量釋放
CH Round #45 - alan有一些陷阱 III題目描述
alan得到一塊由個能量晶體構成的礦石,對於礦石中的每一個能量晶體,如果用化學物質刺激某一個能量晶體,就能使它釋放能量。
它的能量釋放強度與晶體本身的能量值以及能量晶體的位置有關。
為了方便研究,alan做了如下的定義。
能量集:一塊礦石中的第個能量晶體到第個能量晶體(包含和,)構成的集合。
能量儲存點:對於一塊礦石中的能量晶體和,若有,則稱是能量儲存點。
能量釋放點:在一個能量集中,若存在一個能量晶體,使得除它之外的所有能量晶體都是它的能量儲存點,則稱這個能量晶體是該能量集的能量釋放點。
能量釋放強度:對於一個能量集中的能量釋放點來說,刺激這個能量晶體,該能量集中其餘能量晶體會釋放能量。該能量集的能量釋放強度就等於該能量集中其餘某個能量晶體的能量值與能量釋放點的能量值的差的最大值。而第個能量晶體的能量釋放強度則是所在的所有能量集的能量釋放強度的最大值。
alan將給出礦石中能量晶體的個數,以及每個能量晶體的能量值,要求你求出每個能量晶體的能量釋放強度。
輸入格式
第一行1個整數,表示礦石中能量晶體的個數。
第二行個整數,第個整數表示第個能量晶體的能量值。
輸出格式
僅包含一行個整數,第個整數表示第個能量晶體的能量釋放強度。
範例輸入
53 2 1 2 3
範例輸出
0 1 2 1 0
資料範圍與約定
- 對於20%的資料:。
- 對於60%的資料:。
- 對於100%的資料:。
- 溫馨提醒:本題資料量較大,請盡量使用輸入輸出最佳化。
題解:
在考場上我寫的是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 begin11 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 do15 begin16 while (h<t) and (a[i]<a[q[t]]) do17 begin18 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 do26 begin27 while (h<t) and (a[i]<a[q[t]]) do28 begin29 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 begin37 if x>y then exit(x) else exit(y);38 end;39 40 procedure rmq;41 begin42 fillchar(f,sizeof(f),127);43 for i:=1 to n do f[i,0]:=a[i];44 for i:=1 to 22 do45 begin46 if (1<<i)>n then break;47 for j:=1 to n-(1<<i)+1 do48 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 begin54 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 begin60 queue;61 rmq;62 // for i:=1 to n do writeln(l[i],‘ ‘,r[i]);63 for i:=1 to n do64 write(query(l[i],r[i])-a[i],‘ ‘);65 end;66 begin67 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 begin12 readln(n);13 for i:=1 to n do begin read(a[i]);f[i]:=a[i];end;14 end;15 procedure main;16 begin17 a[0]:=-maxlongint;a[n+1]:=-maxlongint;18 l[1]:=1;19 for i:=2 to n do20 begin21 j:=i-1;22 while a[i]<=a[j] do23 begin24 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 do31 begin32 j:=i+1;33 while a[i]<=a[j] do34 begin35 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 begin43 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