zoukankan      html  css  js  c++  java
  • 洛谷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
    ",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
    ",ans);
    18     return 0;
    19 }
  • 相关阅读:
    WPF中ListBoxItem绑定一个UserControl的学习
    Server.Transfer和Response.Redirect的区别
    4个程序员的一天
    (转)让ADO.NET Entity Framework支持Oracle数据库
    IIS操作类
    HttpHandler与HttpModule区别
    网站性能优化的34条黄金法则
    oracle9i/10g/11g各种下载
    WCF简要介绍
    软件系统的稳定性
  • 原文地址:https://www.cnblogs.com/third2333/p/7384246.html
Copyright © 2011-2022 走看看