NOIP2011 day1 T2 选择客栈

来源:互联网 发布:macrar解压软件下载 编辑:程序博客网 时间:2024/05/16 04:58

题目描述

丽江河边有n 家很有特色的客栈,客栈按照其位置顺序从 1 到n 编号。每家客栈都按照某一种色调进行装饰(总共 k 种,用整数 0 ~ k-1 表示),且每家客栈都设有一家咖啡店,每家咖啡店均有各自的最低消费。

两位游客一起去丽江旅游,他们喜欢相同的色调,又想尝试两个不同的客栈,因此决定分别住在色调相同的两家客栈中。晚上,他们打算选择一家咖啡店喝咖啡,要求咖啡店位于两人住的两家客栈之间(包括他们住的客栈),且咖啡店的最低消费不超过 p 。

他们想知道总共有多少种选择住宿的方案,保证晚上可以找到一家最低消费不超过 p元的咖啡店小聚。

题面来自

http://www.luogu.org/problem/show?pid=1311

预处理出一个sum[i]即 [1,i] 中最低消费<=p 的咖啡店的个数,用来判断两个客栈间是否有可以选的咖啡厅,然后枚举颜色相同的最近的两个客栈,若当前枚举的两个客栈合法,那么所有包含该两个客栈的区间都是合法的,这样就可以在O(n)的时间内求出所有合法的客栈的对数。做法为枚举时记录前面不合法的客栈的对数,若当前枚举的一对客栈合法,那么这对客栈前面所有不合法的客栈都可以通过包含这对客栈而变得的合法,具体实现请看代码

#include <cstdio>#include <algorithm>#include <cstring>#include <vector>#define MAXN 200005#define LL long longusing namespace std;LL sum[MAXN],n,k,p,ans=0;vector<LL> color[55]; int main(){    scanf("%lld%lld%lld",&n,&k,&p);    for(int i=1;i<=n;i++)    {        LL a,b;        scanf("%lld%lld",&a,&b);        sum[i]=sum[i-1];        if(b<=p) sum[i]++;        color[a].push_back(i);//颜色为a的客栈的下标    }    for(int i=0;i<k;i++)    {        int cnt=0,num=color[i].size();        for(int j=0;j<color[i].size()-1;j++)        {            if(sum[color[i][j+1]]-sum[color[i][j]-1]>0) ans+=(num-j-1)+cnt*(num-1-j),cnt=0;            else cnt++;        }    }    printf("%lld",ans);}
0 0