NOIP2011 选择客栈(洛谷P1311)

题目描述:

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

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

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

输入格式:

共n+1 行。

第一行三个整数n ,k ,p,每两个整数之间用一个空格隔开,分别表示客栈的个数,色调的数目和能接受的最低消费的最高值;

接下来的n 行,第 i+1 行两个整数,之间用一个空格隔开,分别表示 i 号客栈的装饰色调和i 号客栈的咖啡店的最低消费。

输出格式:

输出只有一行,一个整数,表示可选的住宿方案的总数。

题解:

直接暴力枚举每个客栈,

sum[i][j]表示到第i家客栈为止,颜色为j的客栈数目。

如果客栈最低消费低于p,则求客栈左边到上一次最低消费客栈之间的各种颜色的客栈数目*客栈右边的各种颜色的客栈数目。

这个自己画图yy一下应该就出来了。

代码:

//by lzx 
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
const int N=200010;
int n,k,p;
int sum[N][51];
ll ans=0;
struct node{
    int x,y;
}sa[N];
int main()
{
    scanf("%d%d%d",&n,&k,&p);
    int x,y;
    for(int i=1;i<=k;i++) sum[0][i]=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&x,&sa[i].y);
        for(int j=0;j<k;j++)
        {
            if(x!=j)
            sum[i][j]=sum[i-1][j];
            else sum[i][j]=sum[i-1][j]+1;
        }
        sa[i].x=x;
    }
    int flag=0;
    for(int i=1;i<=n;i++)
    {
        if(sa[i].y<=p)
        {
            
            for(int j=0;j<k;j++)
            {
                int x1=sum[i-1][j]-sum[flag][j],y1=sum[n][j]-sum[i-1][j];
                ans+=x1*y1;
                if(sa[i].x==j)ans+=sum[n][j]-sum[i][j];
            }
            flag=i;
        }
    }
    printf("%lld",ans);
}

 

posted @ 2017-10-21 09:33  LUATS_SOSG  阅读(110)  评论(0)    收藏  举报