【noip 2011】选择客栈

去题面的传送门

QAQ很巧妙的方法 O(n)就可以做
边读入边处理
记录:
①now:为离当前客栈最近的,花费不超过p的客栈的坐标
②sum[x]:已经对答案有过贡献的(与它之后的客栈之间有最小花费不超过p的)颜色为x的客栈的数量
③tot[x]:之前出现过的颜色为x的客栈的数量
④h[x]:之前最后一次出现的颜色为x的客栈(与当前客栈颜色相同且距离当前客栈最近的客栈)的坐标

如何记录答案?

因为我们要找的是颜色相同的两个客栈之间的最小花费小于p,所以只要在两个客栈之间存在一个小于p的,那么他们就是一种方案。所以我们记录了now。如果now在上一个与它颜色相同的客栈之间,那么就对答案有贡献,这时答案应该加上前面所有与它相同颜色的客栈的数量,即tot[x],这时,sum[x]应更新为tot[x]。反之,由于我们记录的sum[x]没有被更新,还是之前的,这时的ans+=sum[x]表示的是该客栈与所有在now之前的与它颜色相同的客栈组成的方案,这时,sum[x]不用更新,因为上一个客栈并没有与当前的客栈形成一种方案。tot[x]每次都要++,同时不要忘了更新h[x]。
注意:由于题目中说两个客栈之间的客栈包括他们两个本身,所以程序中第16、17行不要忘记加等号

由于sum和tot数组及答案的更新并不好理解,所以画个图解释一下:
这里写图片描述
如图 客栈1,2,3,4,5号
上方的数字表示花费,p=3
我们主要说一下4号和5号答案的更新
(用1表示黑色,0表示红色)
4号:
目前,tot[1]=2,sum[1]=0,h[1]=2,now=3
由于在4号和2号之间有花费小于p的客栈(即h[1]<=now),这时我们把sum[1]赋值为tot[1],也就是之前出现过的颜色为黑色的客栈都能与当前客栈形成方案,ans+=sum[1]
5号:
此时,tot[1]=3,sum[1]=2,h[1]=4,now=3
因为在4号和5号之间没有小于p的客栈,此时,不更新sum[1],也就是说,sum[1]还是2,5号对答案的贡献就是5号与之前已经与后面客栈形成方案的颜色为黑的客栈,也就是1号和2号,也就是sum[1]的值

代码:

#include<iostream>
#include<cstdio>
using namespace std;

const int maxn=100+10;
int ans,now,n,k,p;
int h[maxn],tot[maxn],sum[maxn];

int main()
{
    scanf("%d%d%d",&n,&k,&p);
    for(int i=1;i<=n;++i)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        if(y<=p) now=i;//不要忘了等号 
        if(h[x]<=now) sum[x]=tot[x];//等号!! 
        h[x]=i;
        ans+=sum[x];
        tot[x]++;
    }
    printf("%d",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值