水題挑戰1:NOIP 2013 選擇客棧

麗江河邊有\(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

SOLUTION

這題仍是比較簡單的一道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;
}
相關文章
相關標籤/搜索