洛谷P1311 选择客栈

时间复杂度O(N*K)
开两个后缀和数组 a[ i ].color[ j ] 表示在i之后 (包括 i ) 有多少间 客栈是j 颜色的
以及 a[ i ].last 表示在i之后 (包括i ) 第一个小于等于 x 的 咖啡店的坐标

并且要特判一下 a[ i ].last == i 的情况 这是颜色相同的咖啡店数量要减一

 1 #include <cstdio>
 2 #define For(i,j,k) for(int i=j;i<=k;i++)
 3 #define LL long long
 4 using namespace std ;
 5
 6 const int N = 200011 ;
 7 struct node{
 8     int color[50],last,id ;
 9 }a[N];
10 int n,k,pos,alpha,num ;
11 LL sum ;
12 int color[N],money[N] ;
13
14 struct stack{
15     int money,id ;
16 }st[N];
17
18 inline int read()
19 {
20     int x = 0 , f = 1 ;
21     char ch = getchar() ;
22     while(ch<‘0‘||ch>‘9‘) { if(ch==‘-‘) f = -1 ; ch = getchar(); }
23     while(ch>=‘0‘&&ch<=‘9‘) { x = x * 10+ch-48 ; ch = getchar(); }
24     return x * f ;
25 }
26
27 int main()
28 {
29     n = read() ; k = read() ; alpha = read() ;
30     For(i,1,n) {
31         color[ i ] = read() ;
32         money[ i ] = read() ;
33     }
34     for(int i=n;i>=1;i--) {
35         For(j,0,50)
36             a[ i ].color[ j ] = a[ i+1 ].color[ j ] ;
37         a[ i ].color[ color[i] ]++ ;
38     }
39     pos = n+1 ;
40     for(int i=n;i>=1;i--) {
41         if(money[ i ]<=alpha) pos = i ;
42         a[ i ].last = pos ;
43     }
44     For(i,1,n) {
45         pos = a[ i ].last ;
46         num = a[ pos ].color[ color[i] ] ;
47         if( pos==i ) num-- ;
48         sum = sum + num ;
49     }
50     printf("%lld\n",sum) ;
51     return 0 ;
52 }

考虑一个DP,第i个客栈的颜色为x,设f[i]表示i之前(不包括i)颜色为x能用的客栈的数量。
记一下c[x]表示颜色为x的最近的客栈,cnt[x]表示i之前(不包括i)所有颜色为x的客栈总数,
显然c[x]之前的所有能用的客栈,仍然能与客栈i搭配,所以f[i]=f[c[x]];如果c[x]和i可以搭配,
那么i之前所有的客栈全都可以用,所以f[i]=cnt[x],判断的话就看最近的能用的咖啡馆是不是在c[x]之后(含);
答案就是∑f[i]。这时候已经可以得满分了,但是注意到f只与颜色有关,所以可以优化,代码如下:

 1 #include<cstdio>
 2 int n,k,p,i,x,y,lst,f[51],cnt[51],c[51],ans;
 3 int main()
 4 {
 5     scanf("%d%d%d",&n,&k,&p);
 6     for(i=1;i<=n;++i)
 7     {
 8         scanf("%d%d",&x,&y);
 9         if(y<=p)
10             lst=i;
11         if(lst>=c[x])
12             f[x]=cnt[x];
13         ans+=f[x];
14         c[x]=i;
15         ++cnt[x];
16     }
17     printf("%d\n",ans);
18     return 0;
19 }
时间: 2024-12-23 19:45:14

洛谷P1311 选择客栈的相关文章

洛谷 P1311 选择客栈 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1311 题目描述 丽江河边有n 家很有特色的客栈,客栈按照其位置顺序从 1 到n 编号.每家客栈都按照某一种色调进行装饰(总共 k 种,用整数 0 ~ k-1 表示),且每家客栈都设有一家咖啡店,每家咖啡店均有各自的最低消费. 两位游客一起去丽江旅游,他们喜欢相同的色调,又想尝试两个不同的客栈,因此决定分别住在色调相同的两家客栈中.晚上,

洛谷 P1131 选择客栈

题目描述 丽江河边有n 家很有特色的客栈,客栈按照其位置顺序从 1 到n 编号.每家客栈都按照某一种色调进行装饰(总共 k 种,用整数 0 ~ k-1 表示),且每家客栈都设有一家咖啡店,每家咖啡店均有各自的最低消费. 两位游客一起去丽江旅游,他们喜欢相同的色调,又想尝试两个不同的客栈,因此决定分别住在色调相同的两家客栈中.晚上,他们打算选择一家咖啡店喝咖啡,要求咖啡店位于两人住的两家客栈之间(包括他们住的客栈),且咖啡店的最低消费不超过 p . 他们想知道总共有多少种选择住宿的方案,保证晚上可

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

P1311 选择客栈 题目描述 丽江河边有n 家很有特色的客栈,客栈按照其位置顺序从 1 到n 编号.每家客栈都按照某一种色调进行装饰(总共 k 种,用整数 0 ~ k-1 表示),且每家客栈都设有一家咖啡店,每家咖啡店均有各自的最低消费. 两位游客一起去丽江旅游,他们喜欢相同的色调,又想尝试两个不同的客栈,因此决定分别住在色调相同的两家客栈中.晚上,他们打算选择一家咖啡店喝咖啡,要求咖啡店位于两人住的两家客栈之间(包括他们住的客栈),且咖啡店的最低消费不超过 p . 他们想知道总共有多少种选择

【洛谷P1311】选择客栈

这个题听说二分,但是我太菜不会二分,我就会模拟做qwq,时间复杂度O(nk) 我们可以先预处理出所有花费不超过p的咖啡厅,然后预处理一下各色客栈的前缀和. 之后我们假设咖啡厅左边及自己共有li间i色客栈,右边有ri间i色客栈,那么答案应该加上li*ri.但是我们发现这样是会漏掉一种情况的,当这家咖啡厅所在的客栈作为右边被人居住的客栈的时候,我们会漏算.因此我们需要for两边第一遍处理li*ri的情况,第二遍再单独处理咖啡厅作为右端点的情况. #include<iostream> #includ

P1311 选择客栈

题目描述 丽江河边有n 家很有特色的客栈,客栈按照其位置顺序从 1 到n 编号.每家客栈都按照某一种色调进行装饰(总共 k 种,用整数 0 ~ k-1 表示),且每家客栈都设有一家咖啡店,每家咖啡店均有各自的最低消费. 两位游客一起去丽江旅游,他们喜欢相同的色调,又想尝试两个不同的客栈,因此决定分别住在色调相同的两家客栈中.晚上,他们打算选择一家咖啡店喝咖啡,要求咖啡店位于两人住的两家客栈之间(包括他们住的客栈),且咖啡店的最低消费不超过 p . 他们想知道总共有多少种选择住宿的方案,保证晚上可

P1311 选择客栈[模拟]

题目描述 丽江河边有nn家很有特色的客栈,客栈按照其位置顺序从 11到nn编号.每家客栈都按照某一种色调进行装饰(总共 kk 种,用整数 00 ~k-1k?1 表示),且每家客栈都设有一家咖啡店,每家咖啡店均有各自的最低消费. 两位游客一起去丽江旅游,他们喜欢相同的色调,又想尝试两个不同的客栈,因此决定分别住在色调相同的两家客栈中.晚上,他们打算选择一家咖啡店喝咖啡,要求咖啡店位于两人住的两家客栈之间(包括他们住的客栈),且咖啡店的最低消费不超过 pp . 他们想知道总共有多少种选择住宿的方案,

Luogu P1311 选择客栈

暴力 我一开始做这道题先想到的就是暴力... 所以先说一下暴力的做法.首先在输入的时候讲花费小于P的位置标记下来,然后用两层循环枚举所有的两个客栈的组合方案.再用一层循环将两个客栈之间的位置扫一遍,如果有被标记过得位置证明这种方案是可行的.将其统计下来. 暴力的代码 #include <iostream> #include <cstring> #include <cstdio> #include <cstring> const int maxn = 2e5+

noip2011 选择客栈

P1311 选择客栈 375通过 1K提交 题目提供者该用户不存在 标签递推2011NOIp提高组 难度普及+/提高 提交该题 讨论 题解 记录 题目描述 丽江河边有n 家很有特色的客栈,客栈按照其位置顺序从 1 到n 编号.每家客栈都按照某一种色调进行装饰(总共 k 种,用整数 0 ~ k-1 表示),且每家客栈都设有一家咖啡店,每家咖啡店均有各自的最低消费. 两位游客一起去丽江旅游,他们喜欢相同的色调,又想尝试两个不同的客栈,因此决定分别住在色调相同的两家客栈中.晚上,他们打算选择一家咖啡店

Noip2011 提高组 选择客栈

P1311 选择客栈 直通 思路: ①看题,我们可以发现一个显然的性质,即当最左边的客栈向右移动时,最右边的客栈时单调向右的,并且右端点往右的客栈也符合要求.(因为只要左侧有一个满足的,右边的自然可以选) 不妨将每种颜色的宾馆分别放到 vector 中. 然后在每个 vector 中枚举左端点,维护一个单调指针来确定右端点 (vector中的下标). 我们接下来就要快速判断一段区间是否合法,我们开一个ok数组,表示从i点开始最近的满足条件的位置(不考虑颜色). 这样的话转移就是: ok[i]=i