题目链接

题意:
给你nnn个单调不降序列,要从中取kkk个数,每次可以取一个非空序列的第一个元素,并将这个元素从这个序列中删去,问你取的kkk个数得到的最大权值和是多少。

n,k<=3000,n,k<=3000,n,k<=3000,元素总数<=1e6<=1e6<=1e6

题解:
对现在的我来说还是一个挺神仙的题。我觉得我分治水平挺差的,每次见到分治题都会大呼神仙。

暴力做法是背包dp并合并背包,然后显然是O(nk2)O(nk^2)O(nk2)的。然后就没有然后了,应该没法优化了。

首先显然一个序列kkk个以后的元素都没用了,我们就不管了。

这个题首先要发现这个单调不降的性质的用法:对于所有从中选过元素的序列,最终最多有一个序列没有选完。对于任意两个序列,如果在最终方案中他们都没有选完,不妨设这两个序列为a[],b[]a[],b[]a[],b[],分别选到了a[i]a[i]a[i]和b[j]b[j]b[j],那么一定有a[i]>=b[j]a[i]>=b[j]a[i]>=b[j]或者a[i]<=b[j]a[i]<=b[j]a[i]<=b[j],那么我们选较大的那个的后面还没选的若干个来替换小的那个的最后选的这几个,一定会让答案更优,这样直到权值小的那个一个都不选了或者权值大的那个序列全部被选。

有了这个性质之后,我们的想法就是处理出每个序列的权值之和,然后枚举哪个是没全选的序列。

但是很不幸,我们比暴力多发现了一个性质,写出来的东西复杂度却是一样的。

但是这东西好在可以优化。当然就是用我们提到的分治了。

应用典型的思想,我们考虑一个类似线段树的树形分治结构。我们从层数小的向层数大的处理,直到遇到叶节点。
我们递归到一半,然后考虑另一半对这一半的影响。我们的做法是,以先递归到左区间为例,那么我们就先把右区间的每一个序列暴力背包合并,然后递归到左区间,直到区间长度为111,这时候我们就得到了其他每个序列要么全加入,要么全不加入的答案,于是我们当前的这个序列就是可以有剩余的那个。我们枚举这个序列加进去多少个,然后边枚举边维护一个前缀和,然后尝试更新答案即可。对于向右递归,我们也是先暴力将左区间的每一个序列更新背包的dp值即可。

关键在于,分析这么做的复杂度。我们可以发现,对于每个序列,你考虑从根走到这个序列的过程中,每次走向不是它所在的分枝时它会被合并一次,换句话就是每往下一层会用来合并一次,所以用来合并的次数是lognlognlogn的。

注意每次合并之前先清空下一层的dp值。

这样就做完了,复杂度是O(nklogn)O(nklogn)O(nklogn)

好消息是,这个题有代码。
坏消息是,有个我觉得等价的写法,不知道为什么过不了。我觉得等价的写法是我把每个序列的长度截断为它的长度和kkk的minminmin,但是好像错的时候比答案大了,但是我不知道为什么,要是有知道的大佬非常期待您能回答一下(WA test 9)

update:
感谢年糕寿司泡啤酒的帮助。
这里正确性没有问题,但是直接取min会导致读入对不上了。

代码:

#include <bits/stdc++.h>
using namespace std;int n,k,len[3010];
vector<long long> v[3010];
long long s[3010],dp[60][3010],ans;
void solve(int dep,int l,int r)
{if(l==r){long long res=0;ans=max(ans,dp[dep][k]);for(int i=1;i<=min(k,len[l]);++i){res+=v[l][i-1];ans=max(ans,res+dp[dep][k-i]);}return;}int mid=(l+r)>>1;for(int i=0;i<=k;++i)dp[dep+1][i]=dp[dep][i];for(int i=l;i<=mid;++i){for(int j=k;j>=len[i];--j)dp[dep+1][j]=max(dp[dep+1][j-len[i]]+s[i],dp[dep+1][j]);}solve(dep+1,mid+1,r);for(int i=0;i<=k;++i)dp[dep+1][i]=dp[dep][i];for(int i=mid+1;i<=r;++i){for(int j=k;j>=len[i];--j)dp[dep+1][j]=max(dp[dep+1][j-len[i]]+s[i],dp[dep+1][j]);}solve(dep+1,l,mid);
}
int main()
{scanf("%d%d",&n,&k);for(int i=1;i<=n;++i){scanf("%d",&len[i]);for(int j=1;j<=len[i];++j){long long x;scanf("%lld",&x);if(j<=k){v[i].push_back(x);s[i]+=x;}//len[i]=min(len[i],k); //加上这个就会出错}}solve(1,1,n);printf("%lld\n",ans);return 0;
}

CF1442D Sum 分治 背包dp相关推荐

  1. [SPOJ - FTOUR2] Free tour II(点分治 + 背包dp + 启发式合并)

    SPOJ - FTOUR2 Free tour II problem 给定一棵树,以及 mmm 个拥挤城市编号,选择一条最多包含 kkk 个拥挤城市的简单路径. 每条边有一个有趣度 www,可正可负. ...

  2. [CF1442 D] Sum(分治优化dp + 结论)

    CF1442D Sum problem solution code problem luogu翻译 solution 部分分做法,预处理每组前缀和,暴力背包 dpdpdp 转移:dpi,j=max⁡{ ...

  3. 【bzoj4753】[Jsoi2016]最佳团体 分数规划+树形背包dp

    题目描述 JSOI信息学代表队一共有N名候选人,这些候选人从1到N编号.方便起见,JYY的编号是0号.每个候选人都由一位编号比他小的候选人Ri推荐.如果Ri=0则说明这个候选人是JYY自己看上的.为了 ...

  4. 依赖背包dp NOIP2006 vijos 1313 金明的预算方案

    依赖背包: 简化的问题 这种背包问题的物品间存在某种"依赖"的关系.也就是说,物品i依赖于物品j,表示若选物品i,则必须选物品j.为了简化起见,我们先设没有某个物品既依赖于别的物品 ...

  5. (背包dp) 背包N讲

    文章目录 前言 相关练习题 模板题 01背包 完全背包 多重背包 小数据范围 (可朴素暴力) 中等数据范围 (二进制优化) 大数据范围 (单调队列优化) 混合背包 二维费用背包 分组背包 有依赖的背包 ...

  6. 【LibreOJ】#6395. 「THUPC2018」城市地铁规划 / City 背包DP+Prufer序

    [题目]#6395. 「THUPC2018」城市地铁规划 / City [题意]给定n个点要求构造一棵树,每个点的价值是一个关于点度的k次多项式,系数均为给定的\(a_0,...a_k\),求最大价值 ...

  7. 977 AlvinZH过生日(背包DP大作战S)

    977 AlvinZH过生日 思路 难题.逆推DP. 要明确dp的状态只与是否有选择权有关,而与选择权在谁手里无关.因为不论选择权在谁手里,那个人都会尽可能的获得最大的蛋糕重量. dp[i]表示分配到 ...

  8. 背包dp的核心思想(动态规划)

    背包dp 突然发现我一直没有真正理解背包,真正的背包应该是用空间换时间的一种dp方法,本质上就是n个物品选或不选,理论上有2n2^n2n种可能结果,但是背包利用的就是值域很小这一特点来重叠子结构,所以 ...

  9. Codeforces 864E Fire(背包DP)

    背包DP,决策的时候记一下 jc[i][j]=1 表示第i个物品容量为j的时候要选,输出方案的时候倒推就好了 #include<iostream> #include<cstdlib& ...

  10. 【bzoj4007】[JLOI2015]战争调度 暴力+树形背包dp

    题目描述 给你一棵 $n$ 层的完全二叉树,每个节点可以染黑白两种颜色.对于每个叶子节点及其某个祖先节点,如果它们均为黑色则有一个贡献值,如果均为白色则有另一个贡献值.要求黑色的叶子节点数目不超过 $ ...

最新文章

  1. 这可能是近 2 年进京东的最好机会!
  2. 【Flutter学习】组件学习之目录
  3. [转] 一个OpenSource的评价图
  4. Laravel Scheduling Package
  5. SAP中国研究院再次荣获年度中国最佳雇主,国际友人纷纷发来贺电
  6. jquery --- 事件处理函数的event对象的几个属性(方法)说明
  7. ARCGIS知乎上的好文章
  8. java游戏初始化参数过多,从头认识java-4.6 成员的初始化
  9. 神经网络动态可视化工具
  10. QTP的那些事--weblist中相关的内容获取
  11. bat批处理脚本命令大全
  12. 西门子1200plc与施耐德变频器modbus通讯程序
  13. matlab学习笔记 repmat函数与kron函数之区别
  14. 金属类的大宗商品创下新高,对冲基金疯狂买涨
  15. 搭建IP代理池伪装IP地址
  16. libtool 的使用。
  17. 数组循环向左移动k位的算法
  18. 东北大学2018辽宁级计算机专项分数线,2018东北大学各省录取分数线【最新】
  19. 计算机散热程序,电脑的散热方法
  20. 记录使用 Vue 过程中遇到的一些技术点

热门文章

  1. 大型网站 + 静态页面
  2. 在Windows 10中打开PowerShell的9种方法
  3. 计算机应用基础制作新春贺卡图片,WORD制作新年贺卡和个人简历大学计算机基础课程设计报告书...
  4. 图文并茂说明Linux启动流程
  5. Redis简介和优势
  6. Clickhouse除数为0
  7. 金属类的大宗商品创下新高,对冲基金疯狂买涨
  8. Spring MVC 详细信息讲解资料
  9. 下载美国气候数据中心地址
  10. 图文并茂讲VLAN,让你看一遍就理解VLAN