题目描述
丽江河边有 𝑛 家很有特色的客栈,客栈按照其位置顺序从 1 到 𝑛 编号。每家客栈都按照某一种色调进行装饰(总共 𝑘 种,用整数 0∼𝑘−1 表示),且每家客栈都设有一家咖啡店,每家咖啡店均有各自的最低消费。
两位游客一起去丽江旅游,他们喜欢相同的色调,又想尝试两个不同的客栈,因此决定分别住在色调相同的两家客栈中。晚上,他们打算选择一家咖啡店喝咖啡,要求咖啡店位于两人住的两家客栈之间(包括他们住的客栈),且咖啡店的最低消费不超过 𝑝 。
他们想知道总共有多少种选择住宿的方案,保证晚上可以找到一家最低消费不超过 𝑝 元的咖啡店小聚。
输入格式
共 𝑛+1n+1 行。
第一行三个整数 𝑛,𝑘,𝑝,每两个整数之间用一个空格隔开,分别表示客栈的个数,色调的数目和能接受的最低消费的最高值;
接下来的 𝑛 行,第 𝑖+1 行两个整数,之间用一个空格隔开,分别表示 𝑖 号客栈的装饰色调 𝑎𝑖 和 𝑖 号客栈的咖啡店的最低消费 𝑏𝑖。
输出格式
一个整数,表示可选的住宿方案的总数。
样例输入 #2
5 2 3
0 5
1 3
0 2
1 4
1 5
样例输出 #2
3
提示
样例解释
2 人要住同样色调的客栈,所有可选的住宿方案包括:住客栈①③,②④,②⑤,④⑤,但是若选择住 4,54,5号客栈的话,4,54,5 号客栈之间的咖啡店的最低消费是 44 ,而两人能承受的最低消费是 33 元,所以不满足要求。因此只有前 33 种方案可选。
数据范围
- 对于 30%30% 的数据,有 𝑛≤100n≤100 ;
- 对于 50%50% 的数据,有 𝑛≤1 000n≤1000;
- 对于 100%100% 的数据,有 2≤𝑛≤2×1052≤n≤2×105,1≤𝑘≤501≤k≤50,0≤𝑝≤1000≤p≤100,0≤𝑏𝑖≤1000≤bi≤100。
解题思路
解法一
我们知道,我们要求的是有多少客栈满足条件。这道题我们不能一个一个客栈去判断,因为题目要求同色,并且两个客栈之间(包括两客栈)要有咖啡的最低价格没有超过p,这样一来,不满足条件的同色客栈与满足条件的搭配,就也是一种合法搭配,就更复杂了。我们回到最根本的问题,发现,当一个所有都是不合法的客栈的区间内的搭配就都不合法,我们就好判断了。
f[ai][i]=f[c][i-1]+1
当bi小于等于p说明自身就是一个合法客栈,sum+=f[ai][i-1],将前i个,将前i个最近的合法客栈设为i
当bi大于p说明自身是个同色不合法客栈,sum+=f[ai][i-1],它可以和前面所有同色客栈配对。
#include<bits/stdc++.h>
using namespace std;
int n,k,t,f[60][21100],sum=0,c,b,a[210000];
int main(){
cin>>n>>k>>t;
rep(i,1,n){
cin>>c>>b;
if(b<=t){
sum+=f[c][i-1];
a[i]=i;
}
else{
sum+=f[c][a[i-1]];
a[i]=a[i-1];
}
rep(j,0,k){
f[j][i]=f[j][i-1]+(c==j);//c==j是为真(1),其他时候为假(0)。
}
}
cout<<sum;
return 0;
}
方法二
统计之前可以配对的客栈数量,找到同色客栈,进行累加。
#include<bits/stdc++.h>
using namespace std;
int m[55],sum[55],ans,n,k,x;
int main(){
cin>>n>>k>>x;
for(int i=1;i<=n;++i){
int t,ts;
cin>>t>>ts;
if(ts<=x){
for(int j=0;j<=50;++j)
if(m[j]){sum[j]+=m[j];m[j]=0;}
ans+=sum[t];
sum[t]++;
}else{
m[t]++,ans+=sum[t];
}
}
cout<<ans;
return 0;
}