麗江河邊有\(n\) 家頗有特點的客棧,客棧按照其位置順序從 \(1\) 到 \(n\) 編號。每家客棧都按照某一種色調進行裝飾(總共 \(k\) 種,用整數 \(0 \sim k-1\) 表示),且每家客棧都設有一家咖啡店,每家咖啡店均有各自的最低消費。c++
兩位遊客一塊兒去麗江旅遊,他們喜歡相同的色調,又想嘗試兩個不一樣的客棧,所以決定分別住在色調相同的兩家客棧中。晚上,他們打算選擇一家咖啡店喝咖啡,要求咖啡店位於兩人住的兩家客棧之間(包括他們住的客棧),且咖啡店的最低消費不超過 \(p\) 。git
他們想知道總共有多少種選擇住宿的方案,保證晚上能夠找到一家最低消費不超過 \(p\) 元的咖啡店小聚。spa
輸入格式
共 \(n+1\) 行。指針
第一行三個整數 \(n, k, p\),每兩個整數之間用一個空格隔開,分別表示客棧的個數,色調的數目和能接受的最低消費的最高值;code
接下來的 \(n\) 行,第 \(i+1\) 行兩個整數,之間用一個空格隔開,分別表示 \(i\) 號客棧的裝飾色調 \(a_i\) 和 \(i\) 號客棧的咖啡店的最低消費 \(b_i\)。繼承
輸出格式
一個整數,表示可選的住宿方案的總數。ip
輸入輸出樣例
輸入 #1
5 2 3
0 5
1 3
0 2
1 4
1 5
輸出 #1
3
說明/提示
樣例解釋get
2 人要住一樣色調的客棧,全部可選的住宿方案包括:住客棧\(①③,②④,②⑤,④⑤\),可是若選擇住 \(4,5\)號客棧的話,\(4,5\) 號客棧之間的咖啡店的最低消費是 \(4\) ,而兩人能承受的最低消費是 \(3\) 元,因此不知足要求。所以只有前 \(3\) 種方案可選。it
數據範圍
對於 \(30\%\)的數據,有 \(n \leq 100\) ;
對於 \(50\%\)的數據,有 \(n \leq 1\,000\);
對於 \(100\%\)的數據,有 \(2 \leq n \leq 2 \times 10^5\) ,\(1 \leq k \leq 50\),\(0 \leq p \leq 100\) \(0 \leq b_i \leq 100\)io
這題仍是比較簡單的一道noip...acmer的滿滿回憶
1.一個比較暴力的寫法,就是大約\(n^2\times k\) 的效率,用頭尾兩個指針,對每個顏色跑滿整個序列,大約\(50 pts\) .(偷懶的博主掙扎在高數泥潭裏沒法自拔,便懶得寫了 )
2.咱們考慮從前走到後 \(:\)
咱們用 \(f[i][j]\) 來表示前 \(i\) 個位置,對於顏色\(j\)的客棧的答案數.
\(s[i][j]\) 表示前\(i\)個元素,顏色爲\(j\)的客棧數.
\(pos\) 表示離當前位置最近的客棧底下的價格小於等於 \(p\) 咖啡店.
咱們考慮每次走到一個位置 \(i\) : 記它的顏色\(c[i]\) ,則只要在位置是\(pos\)以前的顏色相同的,都會構成一個方案。 即:
當 \(pos\) 與 \(i\) 不一樣
\(f[i][c[i]]=f[i-1][c[i]]+s[pos][c[i]]\)
當 \(pos\)與 \(i\) 相同
\(f[i][c[i]]=f[i-1][c[i]]+s[pos-1][c[i]]\)
其餘顏色位置\(i\)從\(i-1\)繼承而來就行了
具體見代碼
#include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=a;i<=b;i++) #define _(d) while(d(isdigit(ch=getchar()))) template <class T> void g(T&t){T x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch-48;_()x=x*10+ch-48;t=f*x;} typedef long long ll; const int N=200004,K=52; int n,k,p,c[N],v[N],s[N][K];ll f[N][K]; int main(){ g(n),g(k),g(p); rep(i,1,n) g(c[i]),g(v[i]); rep(i,1,n){ rep(j,0,k) s[i][j]=s[i-1][j]; s[i][c[i]]++; } int pos=0; rep(i,1,n){ if(v[i]<=p) pos=i; rep(j,0,k) f[i][j]=f[i-1][j]; if(pos!=i) f[i][c[i]]=f[i-1][c[i]]+s[pos][c[i]]; else f[i][c[i]]=f[i-1][c[i]]+s[pos-1][c[i]]; } ll ans=0; rep(i,0,k) ans+=f[n][i]; printf("%lld\n",ans); return 0; }