好久沒有寫部落格了,今天再寫一篇。還是先看題:
試題描述
阿明是一名推銷員,他奉命到螺絲街推銷他們公司的產品。螺絲街是一條死胡同,出口與入口是同乙個,街道的一側是圍牆,另一側是住戶。螺絲街一共有 n 家住戶,第 i 家住戶到入口的距離為 si 公尺。由於同一棟房子裡可以有多家住戶,所以可能有多家住戶與入口的距離相等。阿明會從入口進入,依次向螺絲街的 x 家住戶推銷產品,然後再原路走出去。阿明每走 1 公尺就會積累 1 點疲勞值,向第 i 家住戶推銷產品會積累 ai 點疲勞值。阿明是工作狂,他想知道,對於不同的 x,在不走多餘的路的前提下,他最多可以積累多少點疲勞值。
輸入第一行有乙個正整數 n,表示街住戶數量,接下來一行有 n 個正整數,其中第 i 個整數 si 表示第 i 家住戶到入口距離保證 s1<=s2<=s3....<10 的 8 次方。接下來一行有 n 個整數,其中第 i 個整數 ai 表示向第 i 個住戶推銷產品會積累疲勞值。保證 ai<=10 的 3 次方。
輸出輸出 n 行,每行乙個正整數,其中第 i 行整數表示當 x=i,阿明積累的疲勞值。
輸入示例
51 2 3 4 5
1 2 3 4 5
輸出示例
1519
2224
25其他說明
資料範圍:1<= n <= 1000000。
針對每乙個x,我在考場當時想能不能用貪心,每一次都選取當前那乙個疲勞值最大的房子,但不知怎麼了,認為不行,覺得應該用dp做,然後就當場懵逼了。現在想何嘗不可以呢?證明很簡單,只要用反證法即可。注意,題目中所說不走多餘路的意思就是推銷x的房子的時候必須一口氣走完,不能繞來繞去,這樣就更能說明了這樣的貪心策略是可以的。本題為去年普及組最後一題,當時沒做出來,現在就秒殺了,感覺自己有很大進步。
貪心策略想好了,下面就開始實現,如何選取當前那乙個疲勞值最大的房子呢?對於乙個沒來過的房子(偏向右端),價值就是s[i]*2+a[i],這裡指的是第乙個,接下來就不一樣了,每一次接下來選擇的都是阿明走過最遠房子的左端或右端中價值最大的房子。對於左端,因為不能走多餘的路,所以價值就是a[i],右端呢,需要加上往返的距離,所以價值就是a[i]+(s[i]-now)*2,其中now指的就是阿明走過最遠房子的位置,然後取乙個最大值即可。如何快速找呢?很容易就能想到可以用乙個最大堆來實現,就用stl裡的priority_queue實現了,優先佇列要宣告兩個,乙個維護now左端的房子,另乙個維護now右端的房子。注意開始時now=0;
想這麼多就差不多可以開始寫了,首先我先無腦寫了乙個結構體node,裡面包含著四種資訊(編號,a[i],s[i],價值),然後就把結構體讀入了,但是到後來才知道:價值是會變的,在讀入中盲目就讀入價值是不行的……之後終於寫完了,提交到oj上,結果時間超限,多交了幾次,有一回999ms卡過了,我就意識到應該是讀入的問題,於是就把scanf改成了read,然後就ac了。
下面是**:
1 #include2 #include3 #include4 #include5 #include6 #include7 #include8using
namespace
std;
9const
int maxn=1000010;10
intn,flag[maxn],ans,s[maxn],a[maxn],now;
11struct
node
18};
19 node max(node a,node b)
20int
read()
2124
while(isdigit(c))
25return x *f;26}
27int
main()
28);//
由於初始位置是now,所以把所有都加入q2,表示在右端36}
37for(int i=1;i<=n;i++)
38,t2=(node);
40if
(q2.size())
4146
if(q1.size())t2=q1.top(),q1.pop();
47 node t0=max(t1,t2);
48if(t0.num==t2.num && t1.num)t1.val+=2*now,q2.push(t1);//注意在擱回q2時,不要忘記將點權在加回2*now
49else
if(t0.num==t1.num)q1.push(t2);//選取t0的操作是選取now左端和右端的點權最大值,在選取之後務必要把那個沒有被選上的房子擱回佇列中,要不就無視那房子了
50 flag[t0.num]=1
;51 ans+=t0.val;
52 printf("
%d\n
",ans);
53if(t0.s>now)
54);
59} 60}
61return0;
62 }
調了很久才叫真正ac。
有幾處小細節,是我在研讀他人**時發現的,我自己編的資料是這樣的:
1 2 3 4 5
10 10 10 20 2
以及它的對稱:
1 2 3 4 5
2 20 10 10 10
就是因為這兩組資料卡爆了多少人,其中包括幸京睿,汪梁森,還有王子健。(然而李琦煜和呂紫劍的程式能完美解決這個問題)問題主要是出在第48,49行**上,具體意思請看旁邊注釋。由此可見,小細節還是十分坑爹的,關於如何解決這些問題的話,還是要多做題吧。
在這裡我來吐槽一下noip普及組給的測試資料究竟有多水,本人在之前有n多個bug的前提下仍舊ac了!!
NOIP 2015 普及組 初賽
noip 2015 普及組 初賽 疑難點 學習 感悟。本份試卷本人得分93,兩處錯誤,一錯在二 1.題,眼花了,多數了個資料3241 二錯在四 2.題 5 空,該空寫成rbound mid 1,這個錯誤在考試中是改正不了的,這是由本人解題方法決定的。也就是說該份試卷本人的極限是98。1.c.1000...
NOIP2015 普及組 金幣
題目描述 國王將金幣作為工資,發放給忠誠的騎士。第一天騎士收到一枚金幣 之後兩天 第二天和第三天 每天收到兩枚金幣 之後三天 第 四 五 六天 每天收到三枚金幣 之後四天,每天收到四枚金幣,以此類推 這種工資發放模式會一直延續下去,當連續n天收到n枚金幣後,騎士會在之後的n 1天,每天收到n 1枚金...
Noip2015普及組題解 金幣(C )
國王將金幣作為工資,發放給忠誠的騎士。第一天,騎士收到一枚金幣 之後兩天 第二天和第三天 每天收到兩枚金幣 之後三天 第 四 五 六天 每天收到三枚金幣 之後四天 第 七 八 九 十天 每天收到四枚金幣 這種工資發放模式會一直這樣延續下去 當連續n天每天收到n枚金幣後,騎士會在之後的連續n 1天裡,...