CF1442D Sum (动态规划,线段树分治)
(
宋
体
字
看
起
来
真
舒
服
)
_{_{(宋体字看起来真舒服)}}
(宋体字看起来真舒服)
题
面
(
洛
谷
翻
译
)
题面_{_{(洛谷翻译)}}
题面(洛谷翻译)
给定
n
n
n个不降的数组。
有一个值
a
n
s
ans
ans,初始为
0
0
0
你需要进行如下操作
k
k
k次:
1.选择一个数组
2.把
a
n
s
ans
ans加上数组的第一个元素。
3.把数组的第一个元素删除。
请求出
a
n
s
ans
ans最大是多少。
所有数组的元素总个数
≤
1
0
6
,
n
,
k
≤
3000
\leq 10^6,n,k\leq 3000
≤106,n,k≤3000
输
入
(
笔
者
亲
自
翻
译
)
输入_{_{(笔者亲自翻译)}}
输入(笔者亲自翻译)
第一行包含两个整数
n
n
n and
k
k
k (
1
≤
n
,
k
≤
3
000
1 \le n, k \le 3\,000
1≤n,k≤3000 ): 分别是数组和操作的数量。
接下来的
n
n
n 行每一行包含一个数组。 每一行的第一个整数是
t
i
t_i
ti (
1
≤
t
i
≤
1
0
6
1 \le t_i \le 10^6
1≤ti≤106 ): 第
i
i
i 个数组的大小。 后面
t
i
t_i
ti 个整数
a
i
,
j
a_{i, j}
ai,j (
0
≤
a
i
,
1
≤
…
≤
a
i
,
t
i
≤
1
0
8
0 \le a_{i, 1} \le \ldots \le a_{i, t_i} \le 10^8
0≤ai,1≤…≤ai,ti≤108 ) 给出了第
i
i
i 个数组。
保证
k
≤
∑
i
=
1
n
t
i
≤
1
0
6
k \le \sum\limits_{i=1}^n t_i \le 10^6
k≤i=1∑nti≤106。
样
例
样例
样例
i
n
p
u
t
input
input
3 3
2 5 10
3 1 2 3
2 1 20
o
u
t
p
u
t
output
output
26
题
解
题解
题解
转换一下模型,相当于一个背包问题,这个不用我多说了吧。
我们会发现一个结论:最后的最优操作一定是把一些数组全选完,最多一个数组只选部分。
S
t
e
p
1
证
明
结
论
Step\;1\;证明结论
Step1证明结论
我们要证这个结论,实际上要证最优操作不存在两个只选了部分的数组:
为了方便证明,我们定义两个数组总和相等的时候,两数组选的数量相差更大的更优
其实很简单,如果存在这么两个数组选了部分:
那么以下两种情况肯定更优:
- a
i
,
x
≥
a
j
,
y
⇒
a
i
,
x
+
1
≥
a
j
,
y
:
a_{i,x} ≥ a_{j,y} \Rightarrow a_{i,x+1} ≥ a_{j,y}:
ai,x≥aj,y⇒ai,x+1≥aj,y:
- a
i
,
x
≤
a
j
,
y
⇒
a
j
,
y
+
1
≥
a
i
,
x
:
a_{i,x} ≤ a_{j,y} \Rightarrow a_{j,y+1} ≥ a_{i,x}:
ai,x≤aj,y⇒aj,y+1≥ai,x:
而这两种情况已经包含全集了(
a
i
,
x
≥
a
j
,
y
a_{i,x} ≥ a_{j,y}
ai,x≥aj,y 和
a
i
,
x
≤
a
j
,
y
a_{i,x} ≤ a_{j,y}
ai,x≤aj,y),所以充分证明了 两个数组都没选完,在中间稳定 的情况是不存在的,因此最多就只有其中一个选完了,另一个没选完的情况。
S
t
e
p
2
利
用
结
论
Step\;2\;利用结论
Step2利用结论
这个结论怎么利用呢?
相当于我们如果确定某一个数组是只选部分的那一个,那么其他的数组就降维了、变成一个数了、一个物品了!
于是我们可以先把其他数组假设成只有一个数,然后把背包跑出来,最后暴力枚举只选部分的那个数组具体选几个。
那么,每一个数组一开始都有一个空的背包dp数组,表示该数组只选部分的情况下其他数组放进来处理的背包。但是这样还是
O
(
n
2
k
)
O(n^2k)
O(n2k) 的过不了。
我们可以想想怎么优化。我们发现每个数组
i
i
i 整个考虑会对
[
1
,
i
−
1
]
∪
[
i
+
1
,
n
]
[1,i-1]∪[i+1,n]
[1,i−1]∪[i+1,n] 内的其他数组的背包有贡献,这是两个区间,因此我们可以用线段树分治优化它,
这样一来每个数组就要对
l
o
g
n
logn
logn 个区间有贡献,而每次贡献是一次
O
(
m
)
O(m)
O(m) 的背包更新,时间复杂度
O
(
n
m
l
o
g
n
)
O(nmlogn)
O(nmlogn)。
最后,由于每个数组挂的区间有特殊性,可以不用真的建一棵线段树,直接判断挂在当前区间的数组有哪些就行了。
C
O
D
E
CODE
CODE
#include<queue>
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 3005
#define LL long long
#define DB double
#define ENDL putchar('\n')//#define lowbit(x) ((-x)&(x))
LL read() {
LL f = 1,x = 0;char s = getchar();
while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
return f * x;
}
const int MOD = 998244353;
int n,m,i,j,s,o,k,sq;
LL dp[100][MAXN];
bool f[100][MAXN];
vector<LL> a[MAXN];
int b[MAXN];
LL ans = 0;
void solve(int l,int r,int de) {
memcpy(dp[de],dp[de-1],sizeof(dp[de]));
memcpy(f[de],f[de-1],sizeof(f[de]));
for(int i = 1;i <= n;i ++) {
if(i == l) {
i = r;continue;
}
if(!f[de][i]) {
f[de][i] = 1;
int tp = a[i][0];
for(int j = m;j >= tp;j --) {
dp[de][j] = max(dp[de][j],dp[de][j-tp] + a[i][tp]);
}
}
}
if(l < r) {
int mid = (l + r) >> 1;
solve(l,mid,de+1);solve(mid+1,r,de+1);
return ;
}
else {
int tp = a[l][0];
ans = max(ans,dp[de][m]);
for(int i = 1;i <= tp && i <= m;i ++) {
ans = max(ans,dp[de][m-i] + a[l][i]);
}
}
return ;
}
int main() {
n = read();m = read();
for(int i = 1;i <= n;i ++) {
s = read();
LL sm = 0;
a[i].push_back(s);
while(s --) {
sm += read();
a[i].push_back(sm);
}
}
solve(1,n,1);
printf("%lld\n",ans);
return 0;
}
CF1442D Sum (动态规划,线段树分治)的更多相关文章
- 【洛谷P4319】 变化的道路 线段树分治+LCT
最近学了一下线段树分治,感觉还蛮好用... 如果正常动态维护最大生成树的话用 LCT 就行,但是这里还有时间这一维的限制. 所以,我们就把每条边放到以时间为轴的线段树的节点上,然后写一个可撤销 LCT ...
- LOJ2312 LUOGU-P3733「HAOI2017」八纵八横 (异或线性基、生成树、线段树分治)
八纵八横 题目描述 Anihc国有n个城市,这n个城市从1~n编号,1号城市为首都.城市间初始时有m条高速公路,每条高速公路都有一个非负整数的经济影响因子,每条高速公路的两端都是城市(可能两端是同一个 ...
- BZOJ_1672_[Usaco2005 Dec]Cleaning Shifts 清理牛棚_动态规划+线段树
BZOJ_1672_[Usaco2005 Dec]Cleaning Shifts 清理牛棚_动态规划+线段树 题意: 约翰的奶牛们从小娇生惯养,她们无法容忍牛棚里的任何脏东西.约翰发现,如果要使这群 ...
- loj#2312. 「HAOI2017」八纵八横(线性基 线段树分治)
题意 题目链接 Sol 线性基+线段树分治板子题.. 调起来有点自闭.. #include<bits/stdc++.h> #define fi first #define se secon ...
- BZOJ.4184.shallot(线段树分治 线性基)
BZOJ 裸的线段树分治+线性基,就是跑的巨慢_(:з」∠)_ . 不知道他们都写的什么=-= //41652kb 11920ms #include <map> #include < ...
- BZOJ.4137.[FJOI2015]火星商店问题(线段树分治 可持久化Trie)
BZOJ 洛谷 一直觉得自己非常zz呢.现在看来是真的=-= 注意题意描述有点问题,可以看BZOJ/洛谷讨论. 每个询问有两个限制区间,一是时间限制\([t-d+1,t]\),二是物品限制\([L,R ...
- 洛谷.3733.[HAOI2017]八纵八横(线性基 线段树分治 bitset)
LOJ 洛谷 最基本的思路同BZOJ2115 Xor,将图中所有环的异或和插入线性基,求一下线性基中数的异或最大值. 用bitset优化一下,暴力的复杂度是\(O(\frac{qmL^2}{w})\) ...
- bzoj4025二分图(线段树分治 并查集)
/* 思维难度几乎没有, 就是线段树分治check二分图 判断是否为二分图可以通过维护lct看看是否链接出奇环 然后发现不用lct, 并查集维护奇偶性即可 但是复杂度明明一样哈 */ #include ...
- BZOJ3237:[AHOI2013]连通图(线段树分治,并查集)
Description Input Output Sample Input 4 5 1 2 2 3 3 4 4 1 2 4 3 1 5 2 2 3 2 1 2 Sample Output Connec ...
随机推荐
- 测试人生 | 薪资翻倍涨至50W是种什么样的体验?
本文为霍格沃兹测试开发学社优秀学员跳槽笔记,测试开发进阶学习文末加群. 本人已经工作7年了,做的都是功能测试以及写一些简单的自动化脚本,加上之前没有学习的意识,导致专业技术水平与工作年限不匹配,在上家 ...
- 关于Vue Element组件el-checkbox与el-select默认选中值的几点注意事项
el-select 示例: 代码: <el-select v-model="doc.zhic" placeholder="请选择"> <el- ...
- 入门Python数据分析最好的实战项目(一)分析篇
数据初探 首先导入要使用的科学计算包numpy,pandas,可视化matplotlib,seaborn,以及机器学习包sklearn. python学习交流群:660193417### import ...
- Java中StringBuffer 简单学习,LeetCode中1323题运用
StringBuffer 学习 StringBuffer() 构造一个没有字符的字符串缓冲区,初始容量为16个字符. deleteCharAt(int index) 删除char在这个指定序列inde ...
- .Net之延迟队列
介绍 具有队列的特性,再给它附加一个延迟消费队列消息的功能,也就是说可以指定队列中的消息在哪个时间点被消费. 使用场景 延时队列在项目中的应用还是比较多的,尤其像电商类平台: 订单成功后,在30分钟内 ...
- Java服务假死后续之内存溢出
一.现象分析 上篇博客说到,Java服务假死的原因是使用了Guava缓存,30分钟的有效期导致Full GC无法回收内存.经过优化后,已经不再使用Guava缓存,实时查询数据.从短期效果来看,确实解决 ...
- JsonPath:针对json的强大的规则解析与参数查找工具
项目特点 GitHub项目地址:https://github.com/json-path/JsonPath 主要功能: 将Json字符串转为Java Map对象(这个不算什么,FastJson之类的工 ...
- 如何在CentOS上找出逐渐耗尽磁盘空间的目录和文件
起因 随着系统运行,CentOS空间不断减少,对此非常焦虑,到底磁盘空间被哪些新增文件占用了呢? 分析过程,主要使用du命令,逐层找出消耗空间的目录 1.在根目录下检索一下文件的占用情况,执行du命令 ...
- 简单的数据结构_via牛客网
题面 链接:https://ac.nowcoder.com/acm/contest/28537/K 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 131072K,其他语 ...
- DateFormat类的format方法和parse方法
/** * 使用DateFormat类中的方法format,把日期格式化为文本 * String format(Date date) 按照指定的模式把Date日期格式化为符合模式的字符串 * 使用步骤 ...