luogu P3592 [POI2015]MYJ
题目链接
题解
区间dp
设f[l][r][k]表示区间l到r内最小值>=k的最大收益
枚举为k的位置p,那么包含p的区间答案全部是k
设h[i][j]表示 当前区间穿过i,且c>=j的区间数量,对i的。
然后我们可以做差分,扫一遍,递推出来
\(f[l][r][k]=max(max(f[l][p][k]+f[p+1][r][k]+h[p][k]×k,p∈[l,r]),f[l][r][k+1])\)
对于c离散化
输出方案吼啊
代码
/*
区间dp
设f[l][r][k]表示区间l到r内最小值>=k的最大收益
枚举为k的位置p,那么包含p的区间答案全部是k
设h[i][j]表示 当前区间穿过i,且c>=j的区间数量,对i的。
然后我们可以做差分,扫一遍,递推出来
f[l][r][k]=max(max(f[l][p][k]+f[p+1][r][k]+h[p][k]×k,p∈[l,r]),f[l][r][k+1])
对于c离散化
*/
#include<cstdio>
#include<algorithm>
using namespace std;
inline int read() {
int x = 0,f = 1;
char c = getchar();
while(c < '0' || c > '9')c = getchar();
while(c <= '9' && c >= '0')x = x * 10 + c -'0',c = getchar();
return x * f;
}
const int maxm = 4007;
const int maxn = 78;
int C[maxm], a[maxm],b[maxm],c[maxm];
int loc[maxn][maxn][maxm];
int dp[maxn][maxn][maxm],h[maxn][maxm];
int n , m , num;
void get_h(int l,int r ) {
for(int i = 1;i <= n;++ i)
for(int j = 1;j <= num;++ j) h[i][j] = 0;
for(int i = 1;i <= m;++ i)
if(l <= a[i] && r >= b[i])
++ h[a[i]][1],-- h[a[i]][c[i] + 1],-- h[b[i] + 1][1],++ h[b[i] + 1][c[i] + 1];
for(int i = l;i <= r;++ i)
for(int j = 1;j <= num;++ j)
h[i][j] += h[i - 1][j] + h[i][j - 1] - h[i - 1][j - 1];
}
int Ans[maxn];
void dfs(int l,int r,int k) {
if(r < l) return;
while(dp[l][r][k] <= dp[l][r][k + 1] && k < num) ++ k;
int Pos = loc[l][r][k];
if(Pos == 0) return ;
Ans[Pos] = C[k];
dfs(l,Pos - 1,k),dfs(Pos + 1,r,k);
}
int main() {
scanf("%d%d",&n,&m);
for(int i = 1;i <= m;++ i)
a[i] = read(),b[i] = read(),C[i] = c[i] = read();
std::sort(C + 1,C + m + 1);
num = unique(C + 1,C + m + 1) - C - 1;
for(int i = 1;i <= m;++ i) c[i] = lower_bound(C + 1,C + num + 1,c[i]) - C;
for(int i = 1;i <= m;++ i)
if(a[i] == b[i])
for(int j = 1;j <= c[i];++ j) dp[a[i]][a[i]][j] += C[j];
for(int i = 1;i <= n;++ i)
for(int j = num - 1;j; -- j) dp[i][i][j] = std::max(dp[i][i][j],dp[i][i][j + 1]);
for(int i = 1;i <= n; ++ i)
for(int j = 0;j <= num; ++ j) loc[i][i][j] = i;
for(int k = 2;k <= n;++ k) {
for(int r, l = 1;l + k - 1 <= n;++ l) {
r = l + k - 1;
get_h(l,r);
for(int i = num;i; --i) {
for(int j = l;j <= r;++ j)
if(dp[l][j - 1][i] + dp[j + 1][r][i] + h[j][i] * C[i] >= dp[l][r][i]) {
dp[l][r][i] = dp[l][j - 1][i] + dp[j + 1][r][i] + h[j][i] * C[i];
loc[l][r][i] = j;
}
if(dp[l][r][i] < dp[l][r][i + 1]) {
dp[l][r][i] = dp[l][r][i + 1];
loc[l][r][i] = loc[l][r][i + 1];
}
}
}
}
int ans = 1;
for(int i = 2;i <= num;++ i) {
if(dp[1][n][i] > dp[1][n][ans]) ans = i;
}
printf("%d\n",dp[1][n][ans]);
dfs(1,n,ans);
for(int i = 1;i <= n;++ i) printf("%d ",Ans[i]);
return 0;
}
luogu P3592 [POI2015]MYJ的更多相关文章
- P3592 [POI2015]MYJ
P3592 [POI2015]MYJ 一道比较烦的区间dp.. 昨天上课讲到了这题,然后就在lg翻到了 然后调了很久很久..... 设\(f[l][r][k]\)为区间\([l,r]\)中,最小值\( ...
- 洛谷 P3592 [POI2015]MYJ
题意 给定\(m\)个区间\([a_i,b_i]\)以及\(c_i\),对于一个含有\(n\)个元素的序列\(ans[]\),区间\(i\)对其的贡献为\(\min\{ans_i\}(i\in[a_i ...
- BZOJ 4386 Luogu P3597 [POI2015]Wycieczki (矩阵乘法)
题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=4386 (luogu) https://www.luogu.org/pro ...
- BZOJ4377 Kurs szybkiego czytania \ Luogu 3589[POI2015]KUR - 数学思维题
Solution 我又双叒叕去看题解啦$QAQ$, 真的想不到鸭 输入 $a$ 和 $n$ 互质, 所以满足 $a \times i \ mod \ n$ $(0<=i<n)$ 肯定是不重 ...
- Luogu 3594 [POI2015]WIL-Wilcze doły
简单题. 考虑没有修改数字的条件的限制,我们直接用双指针扫描就可以计算出答案了. 然后考虑加入修改数字的条件,只要用单调队列维护出当前两个指针表示的区间中长度为$d$的一段区间的最大值,用总和减掉这个 ...
- Luogu 3586 [POI2015]LOG
考虑离散化后开权值线段树. 设序列中不小于$s$的数有$cnt$个,小于$s$的数的和为$sum$. 那么操作Z能成功的充要条件是$sum \geq (c - cnt) * s$. 如果序列中不小于$ ...
- DP没入门就入土
写在前面 记录最近刷的DP题 以及 打死都不可能想到状态设计DP系列 汇总 洛谷 P6082 [JSOI2015]salesman 树形\(\texttt{DP}\) + 优先队列 比较容易看出来这是 ...
- 【做题记录】DP 杂题
P2577 [ZJOI2004]午餐 $\texttt{solution}$ 想到贪心: 吃饭慢的先打饭节约时间, 所以先将人按吃饭时间从大到小排序. 状态: \(f[i][j]\) 表示前 \(i\ ...
- Luogu P3783 [SDOI2017]天才黑客
题目大意 一道码量直逼猪国杀的图论+数据结构题.我猪国杀也就一百来行 首先我们要看懂鬼畜的题意,发现其实就是在一个带权有向图上,每条边有一个字符串信息.让你找一个点出发到其它点的最短路径.听起来很简单 ...
随机推荐
- Python练习-基于socket的FTPServer
# 编辑者:闫龙 import socket,json,struct class MySocket: with open("FtpServiceConfig","r&qu ...
- Entity Framework(EF的Model First方法)
EntityFramework,是Microsoft的一款ORM(Object-Relation-Mapping)框架.同其它ORM(如,NHibernate,Hibernate)一样, 一是为了使开 ...
- UNIX环境高级编程 第10章 信号
SIGSTOP和SIGKILL区别是:前者是使进程暂时停止,即中止,也就是说使进程暂停,将进程挂起,比如你在终端里面执行一个脚本或者程序,执行到一半,你想暂停一下,你按下ctrl+z,就会导致终端发送 ...
- Ajax异步请求struts的JSON机制(省市区三级联动)
1.struts.xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts P ...
- Windows执行命令与下载文件总结
1.前言 在渗透或是病毒分析总是会遇到很多千奇百怪的下载文件和执行命令的方法. 2.实现方式 2.1.Powershell win2003.winXP不支持 $client = new-object ...
- Linux下编译安装qemu和libvirt【转】
转自:http://www.cnblogs.com/findumars/p/5679742.html 目录 [hide] 1 安装qemu 1.1 qemu介绍 1.2 下载源文件 1.3 编译安装 ...
- Python的日志记录-logging模块的使用
一.日志 1.1什么是日志 日志是跟踪软件运行时所发生的事件的一种方法,软件开发者在代码中调用日志函数,表明发生了特定的事件,事件由描述性消息描述,同时还包含事件的重要性,重要性也称为级别或严重性. ...
- liunx系统top命令详解
ps: 1.按1可以进行 CPU各个和总CPU汇总的切换2.cpu0是最关键的,总控管理各个CPU 3.默认情况下仅显示比较重要的 PID.USER.PR.NI.VIRT.RES.SHR.S.%CPU ...
- 八、springboot整合redis
整合Redis 一. 注解方式实现添加缓存 1.在pom.xml加入依赖 <!-- 配置使用redis启动器 --> <dependency> <groupId>o ...
- json在线工具
1.json在线格式化工具 http://www.choujone.com/json/ 2.json在线比较工具 http://tlrobinson.net/projects/javascript-f ...