暴力十分好想但你寫不出來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 }