洛谷 P1311 选择客栈(递推,前缀和)

递推,前缀和
题目意思:
注意,题目要求的是,住宿方案的总数。 比如说,连个旅店 x, y,在 区间[x, y] 之间有 10 个 咖啡店满足
消费 <= p, 但只算一种方案。

本题要点:
1、前缀和:
sum[i] 表示前 i个客栈,咖啡消费小于等于p的数量。
2、用vector v[i] 来存颜色是 i 旅店的编号。 后面就可以按颜色分类计算,假设颜色是 i ,
假设现在已经处理完前k个旅店 也就是说 0, 1, …, k - 1 这几个旅店已经计算完,它们之间可以配对的方案数量。
现在加入 a[k], 新增的 配对,只能是 k 和 0 ~ k - 1 这k个旅店之间的配对。
如果区间 [v[i][k], v[i][k - 1]](v[i][k] 表示 v[i] 里 k坐标的旅店编号), 里面有消费 <= p 的旅店,显然新增的 了配对数量就是 k 对。
如果区间 [v[i][k], v[i][k - 1]] 没有有消费 <= p 的旅店, 那么新增的配对,数量就是 k - 1 和 0 ~ k - 2 这 k - 1 个旅店之间的配对数量了。
3、用个变量,累加 每次新增的配对,得到的就是某种颜色的旅店的方案数。 所有颜色累加就是答案。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
const int MaxN = 200010, MaxK = 51;
int color[MaxN], cost[MaxN];
int sum[MaxN];				// sum[i] 表示前 i个客栈,消费小于等于p的数量
int n, k, p;
vector<int> v[MaxK];

void solve()
{
	long long ans = 0;
	for(int i = 0; i < k; ++i)
	{
		int s = 0,  pre = 0;
		int len = v[i].size();
		for(int j = 1; j < len; ++j)
		{
			if(sum[v[i][j]] - sum[v[i][j - 1] - 1] == 0)
			{
				s += pre;
			}else{
				s += j;
				pre = j;
			}
		}
//		printf("i = %d, len = %d, s = %d\n", i, len, s);
		ans += s;
	}
	printf("%lld\n", ans);
}

int main()
{
	int flag = 0;
	scanf("%d%d%d", &n, &k, &p);
	for(int i = 1; i <= n; ++i)
	{
		scanf("%d%d", &color[i], &cost[i]);
		v[color[i]].push_back(i);
		if(cost[i] <= p)
		{
			flag = 1;
		}else{
			flag = 0;
		}
		sum[i] = sum[i - 1] + flag;
	}
	solve();
	return 0;
}

/*
5 2 3 
0 5 
1 3 
0 2 
1 4 
1 5 
*/

/*
3
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值