bzoj 1584: [Usaco2009 Mar]Cleaning Up 打扫卫生

1584: [Usaco2009 Mar]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

——————题解——————

确实是一道好题。

这题的思路很独特,我yy了半天也只想出了一个n^2的算法,还是太弱了。。

没想到这题的复杂度竟然是n*sqrt(n)。。。

我们假如把序列分为n段,答案显然是n。

我们进行DP是显然不能选一段不同的数>sqrt(n)的,因为一旦选了就肯定达不到最优。

这里还要维护一个量b[j]表示b[j]+1~i有j个不同的数,那么f[i]=min{f[b[j]]+j*j}。

但是怎么搞呢??

我们再定义pre数组,pre[a[i]]为a[i]上一次出现的位置,还有一个c[j]表示b[j]+1~i有c[j]个数不同

在i每次+1的时候,若pre[a[i]]<=b[j],则c[j]++,因为b[j]+1~i这一段没有包含a[i]

那么当前b[j]有变化的肯定是c[j]>j的那些。

然后暴力修改,不知道效率怎么样,但应该还是很快的

最后有个小优化,就是把像1 1 1 1 1这种改为1,对答案没有影响。

#include<stdio.h>
#include<iostream>
using namespace std;
const int Max=2000000000;
const int N=40005;
int n,m,i,j,k,x,a[N],b[N],c[N],pre[N],f[N];
int main()
{
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&x);
        if(x!=a[k]) a[++k]=x;
    }
    for(i=1;i<=k;i++)
        f[i]=Max;
    for(i=1;i<=k;i++)
    {
        for(j=1;j*j<=k;j++)
            if(pre[a[i]]<=b[j]) c[j]++;
        pre[a[i]]=i;
        for(j=1;j*j<=k;j++)
            if(c[j]>j)
        {
            x=b[j]+1;
            while(pre[a[x]]>x) x++;
            b[j]=x;c[j]--;
        }
        for(j=1;j*j<=k;j++)
            f[i]=min(f[i],f[b[j]]+j*j);
    }
    cout<<f[k];
    return 0;
}
时间: 2024-08-08 00:13:19

bzoj 1584: [Usaco2009 Mar]Cleaning Up 打扫卫生的相关文章

DP经典 BZOJ 1584: [Usaco2009 Mar]Cleaning Up 打扫卫生

BZOJ 1584: [Usaco2009 Mar]Cleaning Up 打扫卫生 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 419  Solved: 278 Description 有N头奶牛,每头那牛都有一个标号Pi,1 <= Pi <= M <= N <= 40000.现在Farmer John要把这些奶牛分成若干段,定义每段的不河蟹度为:若这段里有k个不同的数,那不河蟹度为k*k.那总的不河蟹度就是所有段的不河蟹度的总和

【BZOJ】1584: [Usaco2009 Mar]Cleaning Up 打扫卫生

[算法]DP+数学优化 [题意]把n个1~m的数字分成k段,每段的价值为段内不同数字个数的平方,求最小总价值.n,m,ai<=40000 [题解] 参考自:WerKeyTom_FTD 令f[i]表示把前i个数分成若干段的最小价值. 转移中我们定义,从i开始往前到有j个不同的数的最小位置为b[j]. f[i]=f[b[j]-1]+j^2. 考虑最坏情况,每个数自成一段,则总价值为n. 所以当段内不同的数个数>√n时,就不可能是最优解了(此时价值>n). 所以f[i]=f[b[j]-1]+j

动态规划 BZOJ1584 [Usaco2009 Mar] Cleaning Up 打扫卫生

1584: [Usaco2009 Mar]Cleaning Up 打扫卫生 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 511  Solved: 349[Submit][Status][Discuss] Description 有N头奶牛,每头那牛都有一个标号Pi,1 <= Pi <= M <= N <= 40000.现在Farmer John要把这些奶牛分成若干段,定义每段的不河蟹度为:若这段里有k个不同的数,那不河蟹度为k*k.

BZOJ1584 [Usaco2009 Mar]Cleaning Up 打扫卫生

令$f[i]$表示以i为结尾的答案最小值,则$f[i] = min \{f[j] + cnt[j + 1][i]^2\}_{1 \leq j < i}$,其中$cnt[j + 1][i]$表示$[j + 1, i]$内有几个不同的数 对于区间长度为$k$,则答案最大值就是$\sqrt{k}$,所以对于每个$i$我们其实只要枚举$\sqrt{i}$个值就好了 1 /************************************************************** 2 Pr

[BZOJ1584] [Usaco2009 Mar]Cleaning Up 打扫卫生(DP)

传送门 不会啊,看了好久的题解才看懂 TT 因为可以直接分成n段,所以就得到一个答案n,求解最小的答案,肯定是 <= n 的, 所以每一段中的不同数的个数都必须 <= sqrt(n),不然就不是最小的答案 那么 f[i]表示前i个数的最有解 g[i]表示从当前位置开始,有i个不同的数,最多能往前延伸到哪里 pre[i]表示上一个数为i的位置 cnt[i]表示g[i] + 1 ~ 当前位置 中的不同数的个数 所以 f[i] = min(f[i], f[g[j]] + j * j) 那么问题就是g

bzoj1584 9.20考试 cleaning up 打扫卫生

1584: [Usaco2009 Mar]Cleaning Up 打扫卫生 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 549  Solved: 382[Submit][Status][Discuss] Description 有N头奶牛,每头那牛都有一个标号Pi,1 <= Pi <= M <= N <= 40000.现在Farmer John要把这些奶牛分成若干段,定义每段的不河蟹度为:若这段里有k个不同的数,那不河蟹度为k*k.

bzoj 1585: [Usaco2009 Mar]Earthquake Damage 2 地震伤害

1585: [Usaco2009 Mar]Earthquake Damage 2 地震伤害 Description Farmer John的农场里有P个牧场,有C条无向道路连接着他们,第i条道路连接着两个牧场Ai和Bi,注意可能有很多条道路连接着相同的Ai和Bi,并且Ai有可能和Bi相等.Farmer John在1号牧场里.由于地震,某些牧场被损坏,但由于信春哥,C条道路没有一条损坏.有N头奶牛,他们在不同的牧场里,于是N <= P.他们一一向Farmer John报告.第i头奶牛报告给Farm

BZOJ 3399 [Usaco2009 Mar]Sand Castle城堡(贪心)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3399 [题目大意] 将一个集合调整成另一个集合中的数,把一个数+1需要消耗x,-1需要消耗y,问最小消耗. [题解] 显然两个集合排序之后一一对应调整需要消耗的才是最少的,所以排序计算答案即可. [代码] #include <cstdio> #include <algorithm> using namespace std; const int N=25010; int

3400: [Usaco2009 Mar]Cow Frisbee Team 奶牛沙盘队

3400: [Usaco2009 Mar]Cow Frisbee Team 奶牛沙盘队 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 129  Solved: 84[Submit][Status][Discuss] Description 农夫顿因开始玩飞盘之后,约翰也打算让奶牛们享受飞盘的乐趣.他要组建一只奶牛飞盘 队.他的N(1≤N≤2000)只奶牛,每只部有一个飞盘水准指数Ri(1≤Ri≤100000).约翰要选出1只或多于1只奶牛来参加他的