[NOIP2011 提高组] 选择客栈(两种不同解法)

题目描述

丽江河边有 𝑛 家很有特色的客栈,客栈按照其位置顺序从 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;
}

  • 27
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值