• [BZOJ1584]Cleaning Up 打扫卫生


    Description

    有N头奶牛,每头那牛都有一个标号Pi,1 <= Pi <= M <= N <= 40000。现在Farmer John要把这些奶牛分成若干段,定义每段的不河蟹度为:若这段里有k个不同的数,那不河蟹度为k*k。那总的不河蟹度就是所有段的不河蟹度的总和。

    Input

    第一行:两个整数N,M

    第2..N+1行:N个整数代表每个奶牛的编号

    Output

    一个整数,代表最小不河蟹度

    Sample Input

    13 4
    1
    2
    1
    3
    2
    2
    3
    4
    3
    4
    3
    1
    4

    Sample Output

    11
     
    首先有一个很显然的想法,就是任意一段区间的颜色个数不超过$sqrt(len)$个,否则不如$1$个$1$个直接拼
    然后我们只要找如果用$k$种颜色,能从$i$点最远走到哪
    很显然二分+主席树就可以解决了
    我们设$f[i][j]$表示从$i$往只用$j$种颜色最多往前走到哪
    然后讨论一下$C_i$上次出现的位置是否被包含即可转移
    代码:
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstring>
     5 #define M 40010
     6 using namespace std;
     7 int n,m,k;
     8 int lst[M],a[M],dp[M],f[M][210];
     9 int main()
    10 {
    11     scanf("%d%d",&n,&m);k=min((int)sqrt(n),m);
    12     memset(dp,1,sizeof(dp)),dp[0]=0;
    13     scanf("%d",&a[1]);lst[a[1]]=1;
    14     f[1][1]=1;f[1][0]=2;dp[1]=1;lst[a[1]]=1;
    15     for(int i=2;i<=n;i++) 
    16     {
    17         dp[i]=i,f[i][0]=i+1;scanf("%d",&a[i]);
    18         for(int j=1;j<=k;j++)
    19         {
    20             if(lst[a[i]]>=f[i-1][j]&&f[i-1][j]) 
    21                 f[i][j]=f[i-1][j];
    22             else f[i][j]=f[i-1][j-1];
    23         }
    24         for(int j=1;j<=k;j++)
    25             if(f[i][j]-1>=0)
    26                 dp[i]=min(dp[i],dp[f[i][j]-1]+j*j);
    27         lst[a[i]]=i;
    28     }
    29     printf("%d
    ",dp[n]);
    30     return 0;
    31 }
  • 相关阅读:
    密码
    日历游戏
    最大公约数
    从map到hash
    9、RabbitMQ-集成Spring
    8、RabbitMQ-消息的确认机制(生产者)
    7、RabbitMQ-主题模式
    6、RabbitMQ-路由模式
    5、RabbitMQ-订阅模式 Publish/Subscribe
    4、RabbitMQ-消息应答与消息持久化
  • 原文地址:https://www.cnblogs.com/Slrslr/p/10018846.html
Copyright © 2020-2023  润新知