1. 程式人生 > >Codeforces 990E Post Lamps 【暴力】【貪心】

Codeforces 990E Post Lamps 【暴力】【貪心】

返回 stream iostream 而且 %d ios 情況 cout 級別

雖然只是10^6的數據量,但用cin會tle。一直知道cin常數大,但沒想到會是10^3這個級別,而且比scanf慢5倍左右。

我們枚舉每個power的lamp,然後對每個power用平均logn的代價去求它的cost,最後取最小值

對於每個power,我們從左往右地去照亮整個區間,首先0點要插一個路燈,下一個路燈理想上想插在0+power的位置(這樣區間不被重復照亮),但實際上power位置上的路燈可能被blocked了,所以我們想在power位置之前的離power最近的一個位置安裝路燈。如果發現最近的那個位置離power的位置大於power了,那power位置永遠不會被照亮,返回-1

這樣貪心實際上每次算cost的代價是 n/power,為什麽平均意義下是logn的呢。

因為整體下來是n/1+n/2+n/3+n/4+...+n/k,可見k越大整體復雜度越高,我們考慮其上限及k=n的情況,得到n(1+1/2+1/3+1/4+...+1/n),而1+1/2+1/3+1/4+1/5+...+1/n這個數列求和是logn級別的因為可以把1/3+1/4看成1/2,1/5+1/6+1/7+1/8看成1/2,接下來的每8項,16項都是1/2。然後把n看成2^k的話也可以把n看成2^0+2^1+2^2+...+2^k-1,其中每一份都對數列的和貢獻出1/2,所以這個數列求和是1/2*logn左右,及logn級別的。

 1 #include<iostream>
 2 using namespace std;
 3
4 int n,m,k;//長度為n,m個 5 int cost[1000005],blocked[1000005],last_unblocked[1000005]; 6 long long ans; 7 int main() 8 { 9 cin>>n>>m>>k; 10 for(int i=1;i<=m;i++){ 11 int x; scanf("%d",&x); 12 blocked[x]=1; 13 } 14 for(int i=1;i<=k;i++) scanf("%d",&cost[i]); //
power為i的lamp花費cost[i] 15 if(blocked[0]) { cout<<-1; return 0; } 16 17 int last=0; 18 for(int i=1;i<=n;i++){ 19 if(!blocked[i]) last=i; 20 last_unblocked[i]=last; 21 } 22 for(int i=1;i<=k;i++){//模擬用每個power的路燈 23 long long c=0; 24 for(int index=0;index<n; ){//index是每一個要插路燈的位置 25 c+=cost[i]; 26 if(index+i>=n) index=n; 27 else{ 28 int loc=last_unblocked[index+i];//下一個路燈想插在index+i,但這裏可能被blocked了,那想照亮這個地方就找這個位置前面最近能放路燈的位置 29 if(loc<=index) { c=-1; break; } 30 index=loc; 31 } 32 } 33 if(c==-1) continue; 34 else{ 35 if(ans==0) ans=c; 36 else ans=min(c,ans); 37 } 38 } 39 40 if(ans==0) cout<<-1; 41 else cout<<ans; 42 return 0; 43 }

Codeforces 990E Post Lamps 【暴力】【貪心】