• BZOJ1584: [Usaco2009 Mar]Cleaning Up 打扫卫生


    Description

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

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1584

    题解:

    比较神的DP。。。最近怎么老遇神题。。。

     一些注释写在代码里

     1 #include<cstdio>
     2 
     3 #include<cstdlib>
     4 
     5 #include<cmath>
     6 
     7 #include<cstring>
     8 
     9 #include<algorithm>
    10 
    11 #include<iostream>
    12 
    13 #include<vector>
    14 
    15 #include<map>
    16 
    17 #include<set>
    18 
    19 #include<queue>
    20 
    21 #include<string>
    22 
    23 #define inf 1000000000
    24 
    25 #define maxn 50000
    26 
    27 #define maxm 500+100
    28 
    29 #define eps 1e-10
    30 
    31 #define ll long long
    32 
    33 #define pa pair<int,int>
    34 
    35 #define for0(i,n) for(int i=0;i<=(n);i++)
    36 
    37 #define for1(i,n) for(int i=1;i<=(n);i++)
    38 
    39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
    40 
    41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
    42 
    43 #define mod 1000000007
    44 
    45 using namespace std;
    46 
    47 inline int read()
    48 
    49 {
    50 
    51     int x=0,f=1;char ch=getchar();
    52 
    53     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    54 
    55     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
    56 
    57     return x*f;
    58 
    59 }
    60 int n,m,a[maxn],b[maxn],c[maxn],f[maxn],pre[maxn];
    61 
    62 int main()
    63 
    64 {
    65 
    66     freopen("input.txt","r",stdin);
    67 
    68     freopen("output.txt","w",stdout);
    69 
    70     n=read();m=read();m=sqrt(n);
    71     for1(i,n)a[i]=read();
    72     memset(f,60,sizeof(f));
    73     memset(pre,-1,sizeof(pre));//pre[i]表示i在序列中上一次出现的位置
    74     f[0]=0;
    75     for1(i,n)
    76     {
    77         for1(j,m)if(pre[a[i]]<=b[j])c[j]++;//b[j]表示b[j]+1到i有<=j个不同的数字
    78         pre[a[i]]=i;
    79         for1(j,m)
    80         if(c[j]>j)//c[j]表示b[j]+1到i出现的不同数字的个数,如果>j显然不合b[j]的定义,所以要删数
    81          {
    82              int t=b[j]+1;//指针
    83              while(pre[a[t]]>t)t++;//往前扫,pre[a[t]]>t表示在t到i之间还有a[t],所以继续前移,知道出现某个数的后继还没有出现,意为在i之后
    84              b[j]=t;c[j]--;
    85          }
    86         for1(j,m)f[i]=min(f[i],f[b[j]]+j*j);
    87     }
    88     printf("%d
    ",f[n]);
    89 
    90     return 0;
    91 
    92 }
    View Code

     

     

     

  • 相关阅读:
    找出优先要作的工作
    我要作技术研发了
    确定配色方案
    今天公司搬家
    要作界面原型了
    使用自已的命名空间
    进行审核了
    那里有皮肤软件工开发包的源码???
    发葡萄
    作业务规则挺难
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/4060025.html
Copyright © 2020-2023  润新知