选择客栈

 原题链接:https://www.luogu.org/problem/show?pid=1311#sub

暴力好想不好写,正解好写不好想。

刚开始读题的时候总给我一个感觉,那就是k可以不用。因为我们有时根本没必要去关心它的编号具体是什么。后来发现还真是。

如果是暴力枚举客栈的话,不能同时枚举两个客栈,那样会超时,所以只能同时枚举一个。我们枚举第二个客栈,然后用第二个客栈反推出前面的方案数。

思路就是,从1到n枚举,输入color和price的值,我们需要记录一个距离第二个客栈最近的咖啡厅价钱合理的客栈位置,用一个now变量记录。

开三个辅助数组,last[i]表示最后一个以i为颜色的客栈的位置,cnt[i]表示以i为颜色的客栈总数,sum[i]可以看作是一个临时数组,用来存储当前的方案数。

可以这么想,当前枚举到一个客栈i,这个i是第二个客栈,那么显然第一个客栈一定在第二个客栈之前,编号必定是0~i-1之间的一个数。如果我发现枚举的时候在某一个客栈前面有一个价钱合理的咖啡厅,那么在这之前的任何一个同色客栈都是第一个客栈可以选的,那么统计一下数量,这就是当前的方案数。

然后更新last数组,更新ans,让cnt[color]++,这样从左到右地推过来就好了。

这个解法简化于暴力算法,暴力算法要循环三层,一层1客栈,二层2客栈,3层合理的位置,这样做显然不行,而我们做的就是去优化掉两层,而是从枚举2客栈出发推出1客栈的位置和所有可行方案,所以这样做是正确的。最后输出即可。

参考代码:

 1 #include <iostream>
 2 #define maxn 200005
 3 using namespace std;
 4 int n,k,p;
 5 int color,price;
 6 int last[maxn];
 7 int sum[maxn];
 8 int cnt[maxn];
 9 int ans = 0;
10 int now;
11 int main(){
12     cin >> n >> k >> p;
13     for (int i=1;i<=n;i++){
14         cin >> color >> price;
15         if (price <= p)
16             now = i;
17         if (now >= last[color])
18             sum[color] = cnt[color];
19         last[color] = i;
20         ans += sum[color];
21         cnt[color]++;
22     }
23     cout << ans << endl;
24     return 0;
25 }

 

转载于:https://www.cnblogs.com/OIerShawnZhou/p/7538544.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值