题目描述

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

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

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

分析

很明显维护两个颜色相同的区间最小值,取每次取min判断是否不超过p即可.

一 :O(n^3)做法,就是暴力嘛 emmm 略过了

二 :O(假的n^3)做法,时间复杂度并不会证明

数组last记录每个位置i的上一个相同颜色的位置
数组head[color]记录颜色color最后一次出现的位置
记录完之后就类似链式前向星地跑就可以了

吸氧之后可以70pts

不吸氧的话60pts

代码:

#include<bits/stdc++.h>
#define IL inline
#define RI register int
#define N 200008
#define ls o<<1
#define rs o<<1|1
IL void read(int &x){
int f=1;x=0;char s=getchar();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
while(s<='9'&&s>='0'){x=x*10+s-'0';s=getchar();}
x*=f;
}
int n,k,p,ans;
int ST[N][21];
int head[N],last[N];
//k为色调数目,p为最低最多能花的钱.
struct STbiao
{
IL void pre()
{
for(RI j=1;(1<<j)<=n;j++)
for(RI i=1;i+(1<<j)-1<=n;i++)
ST[i][j]=std::min(ST[i][j-1],ST[i+(1<<(j-1))][j-1]);
}
IL int query(int l,int r)
{
int k=log2(r-l+1);
return std::min(ST[l][k],ST[r-(1<<k)+1][k]);
}
}st;
int main()
{
read(n),read(k),read(p);
for(RI i=1,col;i<=n;i++)
{
read(col),read(ST[i][0]);
last[i]=head[col];
head[col]=i;
}
st.pre();
for(RI c=0;c<k;c++)
for(RI i=head[c];i;i=last[i])
for(RI j=last[i];j;j=last[j])
if(st.query(j,i)<=p)ans++;
printf("%d",ans);
}

三 考虑优化ST

优化思想借鉴于 @ShawnZhou

我们可以再维护两个数组pre和cnt

pre[i]数组记录到当前位置颜色为i的价值小于等于p的客栈个数
cnt[i]数组记录到当前位置颜色i出现次数

因此我们可以减少枚举次数,从而达到优化时间的目的。

-----------------AC代码-----------------

#include<bits/stdc++.h>
#define IL inline
#define RI register int
#define N 200008
#define ls o<<1
#define rs o<<1|1
IL void read(int &x){
int f=1;x=0;char s=getchar();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
while(s<='9'&&s>='0'){x=x*10+s-'0';s=getchar();}
x*=f;
}
int n,k,p,ans;
int ST[N][21];
int head[N],last[N],color[N],cnt[N],pre[N];
//k为色调数目,p为最低最多能花的钱.
struct STbiao
{
IL void pre()
{
for(RI j=1;(1<<j)<=n;j++)
for(RI i=1;i+(1<<j)-1<=n;i++)
ST[i][j]=std::min(ST[i][j-1],ST[i+(1<<(j-1))][j-1]);
}
IL int query(int l,int r)
{
int k=log2(r-l+1);
return std::min(ST[l][k],ST[r-(1<<k)+1][k]);
}
}st;
int main()
{
read(n),read(k),read(p);
for(RI i=1,col;i<=n;i++)
read(color[i]),read(ST[i][0]);
st.pre();
for(RI i=1;i<=n;i++)
{
if(!head[color[i]])
{
cnt[color[i]]++;
head[color[i]]=i;
}
else
{
if(st.query(head[color[i]],i)<=p)
ans+=cnt[color[i]],pre[color[i]]=cnt[color[i]];
//如果当前位置与上一颜色相同位置之间有任意一家客栈的花费小于等于p
//那么我们就可以选择当前位置的客栈与更之前位置的客栈
//并更新可以对答案贡献的数组.
else
ans+=pre[color[i]];
cnt[color[i]]++;head[color[i]]=i;
}
}//这一层for即为优化后的,其他位置并没有改动。
printf("%d",ans);
}

ST表【p1311】 选择客栈的更多相关文章

  1. 洛谷 P1311 选择客栈 解题报告

    P1311 选择客栈 题目描述 丽江河边有 \(n\) 家很有特色的客栈,客栈按照其位置顺序从 \(1\) 到 \(n\) 编号.每家客栈都按照某一种色调进行装饰(总共 \(k\) 种,用整数 \(0 ...

  2. 洛谷P1311 选择客栈

    P1311 选择客栈 题目描述 丽江河边有n 家很有特色的客栈,客栈按照其位置顺序从 1 到n 编号.每家客栈都按照某一种色调进行装饰(总共 k 种,用整数 0 ~ k-1 表示),且每家客栈都设有一 ...

  3. Luogu P1311 选择客栈(前缀和)

    P1311 选择客栈 题意 题目描述 丽江河边有\(n\)家很有特色的客栈,客栈按照其位置顺序从\(1\)到\(n\)编号.每家客栈都按照某一种色调进行装饰(总共\(k\)种,用整数\(0\)~\(k ...

  4. 【洛谷】【st表+模拟】P1311 选择客栈

    [题目描述:] 丽江河边有n 家很有特色的客栈,客栈按照其位置顺序从 1 到n 编号.每家客栈都按照某一种色调进行装饰(总共 k 种,用整数 0 ~ k-1 表示),且每家客栈都设有一家咖啡店,每家咖 ...

  5. P1311 选择客栈[模拟]

    题目描述 丽江河边有nn家很有特色的客栈,客栈按照其位置顺序从 11到nn编号.每家客栈都按照某一种色调进行装饰(总共 kk 种,用整数 00 ~k-1k−1 表示),且每家客栈都设有一家咖啡店,每家 ...

  6. [NOIP2011] 提高组 洛谷P1311 选择客栈

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

  7. 洛谷 P1311 选择客栈

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

  8. 2011 luogu P1311 选择客栈

    题目描述 丽江河边有 nn 家很有特色的客栈,客栈按照其位置顺序从 1 到 n 编号.每家客栈都按照某一种色调进行装饰(总共 k 种,用整数 0 ~ k-1 表示),且每家客栈都设有一家咖啡店,每家咖 ...

  9. 洛谷 P1311 选择客栈 —— 水题

    题目:https://www.luogu.org/problemnew/show/P1311 看每个位置能否成为咖啡店,然后作为客栈和前面配对即可. 代码如下: #include<iostrea ...

  10. 洛谷——P1311 选择客栈

    https://www.luogu.org/problem/show?pid=1311 题目描述 丽江河边有n 家很有特色的客栈,客栈按照其位置顺序从 1 到n 编号.每家客栈都按照某一种色调进行装饰 ...

随机推荐

  1. .net 匿名方法

    匿名方法 核心就是lambda语法,下面是使用举例: var conn= MySqlHelper.GetConn(); var list=conn.Query<User>("SE ...

  2. Kotlin中功能操作与集合(KAD 11)

    作者:Antonio Leiva 时间:Feb 2, 2017 原文链接:https://antonioleiva.com/functional-operations-collections-kotl ...

  3. SELECTORS模块实现并发简单版FTP

    环境:windows, python 3.5功能:使用SELECTORS模块实现并发简单版FTP允许多用户并发上传下载文件 结构:ftp_client ---| bin ---| start_clie ...

  4. 2、shader基本语法、变量类型、shader的三种形式、subshader、fallback、Pass LOD、tags

    新建一个shader,名为MyShader1内容如下: 1._MainTex 为变量名 2.“Base (RGB)”表示在unity编辑面板中显示的名字,可以定义为中文 3.2D 表示变量的类型 4. ...

  5. java初学4

    1.interface接口 (1)[修饰符] interface 接口名 extends 父接口1,父接口2....        •没有构造方法,不能实例化;        •接口只能继承接口,不能 ...

  6. 搭建 MongoDB分片(sharding) / 分区 / 集群环境

    1. 安装 MongoDB 三台机器 关闭防火墙 systemctl stop firewalld.service 192.168.252.121 192.168.252.122 192.168.25 ...

  7. EK算法模板

    #include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> ...

  8. 发现一个form小问题

    在使用编辑器及框架时,form表单如果在太靠内的div层里,就取不到textarea的post值,具体原因位置,可能跟框架的CSS有关

  9. server reached pm.max_children setting (5), consider raising it

    先查看日志 /data1/server/php-cgi/var/log/php-fpm.log[19-Dec-2012 11:41:13] WARNING: [pool www] server rea ...

  10. 使用java的自定义过滤器Filter 处理请求request 并响应response

    package com.enation.eop; import java.io.BufferedReader; import java.io.IOException; import java.io.I ...