洛谷P1311 选择客栈

Posted third2333

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷P1311 选择客栈相关的知识,希望对你有一定的参考价值。

洛谷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 }

 

以上是关于洛谷P1311 选择客栈的主要内容,如果未能解决你的问题,请参考以下文章

洛谷 P1311 选择客栈 题解

洛谷P1311选择客栈

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

Luogu P1311 选择客栈

P1311 选择客栈

P1311 选择客栈