LG-P1311選擇客棧

Wesukilaye發表於2018-10-28

題目

暴力十分好想但你寫不出來qwq

正解十分好寫但你想不出來qaq

我們先讀題,發現k其實沒什麼用

同時暴力列舉兩個客棧的話會超時,所以只能同時列舉一個。我們列舉第二個客棧,然後用第二個客棧反推出前面的方案數。

思路就是,從1到n列舉,輸入顏色color和價錢price,我們需要記錄一個距離第二個客棧最近且價錢合理(小於等於p)的咖啡廳的客棧位置,用變數now記錄。

然後開三個輔助陣列,last[i]表示最後一個以i為顏色的客棧的位置,cnt[i]表示以i為顏色的客棧總數,sum[i]可以看作是一個臨時陣列,用來儲存當前的方案數。

可以這麼想,當前列舉到一個客棧i,這個i是第二個客棧,那麼顯然第一個客棧一定在第二個客棧之前,編號必定是0~i-1之間的一個數。如果我發現列舉的時候在某一個客棧前面有一個價錢合理的咖啡廳,那麼在這之前的任何一個同色客棧都是第一個客棧可以選的,那麼統計一下數量,這就是當前的方案數。

然後更新last陣列,更新ans,讓cnt[color]++,這樣從左到右地推過來就好了。

這個解法簡化於暴力演算法,暴力演算法要迴圈三層,一層1客棧,二層2客棧,3層合理的位置,這樣做顯然不行,而我們做的就是去優化掉兩層,從列舉2客棧出發推出1客棧的位置和所有可行方案,所以這樣做是正確的。最後輸出即可。

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 
 7 int n,k,p;
 8 int color,price,now,ans;
 9 int last[55],sum[55],cnt[55];
10 
11 int main()
12 {
13     ios::sync_with_stdio(false);//關同步,讓你的cin,cout快過scanf,printf!
14     cin>>n>>k>>p;
15     for(int i=1; i <= n; i++){
16         cin>>color>>price;
17         if(price <= p)
18             now=i;
19         if(now >= last[color])
20             sum[color]=cnt[color];
21         last[color]=i;
22         cnt[color]++;
23         ans += sum[color];
24     }
25     cout<<ans<<"
";//
比endl快8倍
26     return 0;
27 }

相關文章