1. 程式人生 > >[Luogu] 選擇客棧

[Luogu] 選擇客棧

getchar() 之間 tps printf iostream 輔助 兩層 show 一個數

https://www.luogu.org/problemnew/show/P1311

思路就是,從1到n枚舉,輸入color和price的值,我們需要記錄一個距離第二個客棧最近的咖啡廳價錢合理的客棧位置,用一個now變量記錄。

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

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

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

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

#include<cstdio>
#include <iostream>

const int N = 200100;

#define gc getchar() 

inline int read() {
    int x = 0; char c = gc;
    
while(c < 0 || c > 9) c = gc; while(c >= 0 && c <= 9) x = x * 10 + c - 0, c = gc; return x; } int n,k,p,col,mon,now,ans; int num[N],s[N],c[N]; int main() { n = read(); k = read(); p = read(); for(int i = 1; i <= n; ++ i) { col = read(); mon = read(); if
(mon <= p) now = i; if(now >= c[col]) s[col] = num[col]; c[col] = i; ans += s[col]; num[col] ++; } printf("%d", ans); return 0; }

[Luogu] 選擇客棧