【CF1133E】K Balanced Teams(动态规划,单调队列)

【CF1133E】K Balanced Teams(动态规划,单调队列)

题面

CF
让你把一堆数选一些出来分成不超过\(K\)组,每一组里面的最大值和最小值之差不超过\(5\),求最多有多少个人元素可以被分组。

题解

设\(f[i][j]\)表示把前\(i\)个数分成\(j\)组的最多人数。
然后单调队列转移一下完了。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define MAX 5050
inline int read()
{
    int x=0;bool t=false;char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=true,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return t?-x:x;
}
int n,K,ans,f[MAX][MAX],a[MAX],Q[MAX][MAX],h[MAX],t[MAX];
int main()
{
    n=read();K=read();
    for(int i=1;i<=n;++i)a[i]=read();
    sort(&a[1],&a[n+1]);
    for(int j=0;j<=K;++j)h[j]=1;
    for(int i=1;i<=n;++i)
    {
        for(int j=0;j<=K;++j)f[i][j]=f[i-1][j];
        for(int j=0;j<=K;++j)f[i][j+1]=max(f[i][j+1],f[i-1][j]+1);
        for(int j=0;j<=K;++j)
        {
            while(h[j]<=t[j]&&a[i]-a[Q[j][h[j]]]>5)++h[j];
            if(h[j]<=t[j])f[i][j+1]=max(f[i][j+1],f[Q[j][h[j]]-1][j]+i-Q[j][h[j]]+1);
            while(h[j]<=t[j]&&f[Q[j][t[j]]-1][j]-Q[j][t[j]]<=f[i-1][j]-i)--t[j];
            Q[j][++t[j]]=i;
        }
    }
    for(int i=0;i<=K;++i)ans=max(ans,f[n][i]);
    printf("%d\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/cjyyb/p/10655807.html

时间: 2024-10-17 13:46:12

【CF1133E】K Balanced Teams(动态规划,单调队列)的相关文章

题解CF1133E K Balanced Teams

题目:CF1133E K Balanced Teams 拿到手第一想法就是算一下每个人可以和他分一起的,然后贪心.很显然在1s内被自己hack.所以贪心不行优先考虑dp.看到n和k的范围明显是个O(n^2)的dp. 由于我们不考虑顺序,按常规把水平排个序. 我的最初想法: 设f[i][j]:前i个人分了j组的最大和. 1.h[i]-h[lst]<=5 我们可以把他分到j-1组也可以分到第j组 2.h[i]-h[lst]>5 只能把i分到第j组 但我们遇到一个问题,就是我们不清楚第j-1组的开头

BZOJ_1096_[ZJOI2007]_仓库建设_(斜率优化动态规划+单调队列+特殊的前缀和技巧)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1096 有\(n\)个工厂,给出第\(i\)个工厂的到1号工厂的距离\(x[i]\),货物数量\(p[i]\),建设仓库所需花费\(c[i]\). 现在要把所有货物都装入仓库,第\(i\)号工厂的货物可以选择在\(i\)建仓库并存入,或者移动到\(k\)号仓库\((i<k<=n)\).移动的花费为数量与距离的乘积. 分析 我们来想一想dp方程. 用\(dp[i]\)表示前\(i\)个工厂,且

BZOJ_1010_[HNOI2008]_玩具装箱toy_(斜率优化动态规划+单调队列)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1010 给出\(n\)和\(l\).有\(n\)个玩具,第\(i\)个玩具的长度是\(c[i]\),要求将玩具分成若干段,从\(i\)到\(j\)分为一段的长度为\(x=j-i+\sum_(k=i)^jc[k]\),费用为\((x-l)^2\).求最小费用. 分析 用\(dp[i]\)表示前\(i\)个玩具所需的最小费用,则有$$dp[i]=min\{dp[j]+(sum[i]-sum[j]+

codeforces 1133E K Balanced Teams

题目链接:http://codeforces.com/contest/1133/problem/E 题目大意: 在n个人中找到k个队伍.每个队伍必须满足最大值减最小值不超过5.求满足条件k个队伍人数的总和的最大值. 这个题写DP很多的人应该可以很快写出来吧,毕竟不是很难. 思路: 反正最多n^2种状态.用数组存就好了. 先排序. 对于每个点,dp[a][b].表示a到n区间里分b个队伍的答案. 如果a是答案dp[a][b]所需要的,那么我们从a开始到a+i暴力一下(此时,x[a+i]-x[a]>

CF #544 div3 E. K Balanced Teams

题意:有n个学生 要求组成k个小组 每个小组中两两差值不得超过5 可以有学生不被编入组中 求最多可以有多少个学生被编入组中 n,k<=1e5 题解: 考虑dp[i][j],i为前i个学生,j为分了几组的最大人数,不选第i个人,dp[i][j]=dp[i-1][j], 选第i个人,贪心的选择距离a[i]小于等于5的最远那个点-1,记作pos[i],dp[i][j]=dp[pos[i]][j-1]+i-pos dp[i][j]=max(dp[i-1][j],dp[pos[i]][j-1]+i-pos

[USACO13OPEN]照片Photo [动态规划 单调队列]

[USACO13OPEN]照片Photo 这题好烧脑... #include<bits/stdc++.h> using namespace std; #define ll long long #define rg register #define Max(x,y) ((x)>(y)?(x):(y)) #define Min(x,y) ((x)>(y)?(y):(x)) const int N=2e5+5,M=1e5+5,inf=0x3f3f3f3f,P=19650827; int

详解--单调队列 经典滑动窗口问题

单调队列,即单调的队列.使用频率不高,但在有些程序中会有非同寻常的作用. 动态规划·单调队列的理解 做动态规划时常常会见到形如这样的转移方程: f[x] = max or min{g(k) | b[x] <= k < x} + w[x] (其中b[x]随x单调不降,即b[1]<=b[2]<=b[3]<=...<=b[n]) (g[k]表示一个和k或f[k]有关的函数,w[x]表示一个和x有关的函数) 这个方程怎样求解呢?我们注意到这样一个性质:如果存在两个数j, k,使

Tyvj1305最大子序和(单调队列优化dp)

描述 输入一个长度为n的整数序列,从中找出一段不超过M的连续子序列,使得整个序列的和最大. 例如 1,-3,5,1,-2,3 当m=4时,S=5+1-2+3=7当m=2或m=3时,S=5+1=6 输入格式 第一行两个数n,m第二行有n个数,要求在n个数找到最大子序和 输出格式 一个数,数出他们的最大子序和 测试样例1 输入 6 4 1 -3 5 1 -2 3 输出 7 备注 数据范围:100%满足n,m<=300000 是不超过m,不是选m个!!!!! /* 单调队列优化dp 单调队列维护的是前

ZOJ 3632 Watermelon Full of Water(dp+线段树或单调队列优化)

Watermelon Full of Water Time Limit: 3 Seconds      Memory Limit: 65536 KB Watermelon is very popular in the hot summer. Students in ZJU-ICPC Team also love watermelon very much and they hope that they can have watermelon to eat every day during the