题意

给定\(m\)个区间\([a_i,b_i]\)以及\(c_i\),对于一个含有\(n\)个元素的序列\(ans[]\),区间\(i\)对其的贡献为\(\min\{ans_i\}(i\in[a_i,b_i])<=c_i\ ?\ \min\{ans_i\}(i\in[a_i,b_i])\ :\ 0\),要求构造一个序列\(ans[]\),最大化区间的贡献之和。

\(n\leq50,m\leq4000\)

思路

离散化+区间\(\texttt{DP}\)

打死都不可能想到状态设计DP系列

稍作分析半天就会发现:存在一组答案使得每个\(ans_i\)都是某个\(c_i\)。因为把某个答案替换成第一个大于等于它的\(c_i\)不会更劣,因此\(c_i\)的值并不影响做题,但是大小顺序是有用的所以我们将\(c_i\)离散化。

因为一个区间的代价之和只与最小值有关,而且数据范围的\(n\)也不大,所以考虑区间\(\texttt{DP}\):

设\(f[l][r][k]\)表示区间\([l,r]\)内\(ans[]\)的最小值等于\(k\)的最大收益,\(g[p][j]\)为当前区间穿过\(p\),且\(c\geq j\)的区间数量

枚举最小的位置\(p\),那么包含\(p\)的区间的答案全都是\(k\),之后转移

\[f[l][r][k]=\max(\max(f[l][p - 1][k] + f[p + 1][r][k]+g[p][k]*k,p\in[l,r]),f[l][r][k+1])
\]

\(\texttt{DP}\)时顺便记录记录决策点,然后\(dfs\)输出

时间复杂度\(O(n^3m)\)

代码

/*
Author:Loceaner
区间DP
*/
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; const int A = 51;
const int B = 4011;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f; inline int read() {
char c = getchar(); int x = 0, f = 1;
for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
return x * f;
} struct node { int l, r, c; } a[B];
int n, m, tot, ans[B], res[B];
int pre[A][A][B], f[A][A][B], pos[A][A][B], g[A][B]; inline void work(int l, int r, int now) {
if (l > r) return;
int qwq = pos[l][r][now = pre[l][r][now]];
ans[qwq] = res[now];
work(l, qwq - 1, now), work(qwq + 1, r, now);
} inline void update(int l, int r) {
for (int i = l; i <= r; i++)
for (int minn = 0; minn <= tot; minn++) g[i][minn] = 0;
for (int i = 1; i <= m; i++)
if (l <= a[i].l && a[i].r <= r)
for (int j = a[i].l; j <= a[i].r; j++) g[j][a[i].c]++;
for (int i = l; i <= r; i++)
for (int j = tot - 1; j >= 1; j--) g[i][j] += g[i][j + 1];
} inline void dp(int l, int r) {
for (int k = tot; k >= 1; k--) {
int maxn = 0;
for (int p = l; p <= r; p++) {
int now = f[l][p - 1][k] + f[p + 1][r][k] + g[p][k] * res[k];
if (maxn <= now) maxn = now, pos[l][r][k] = p;
}
if (maxn >= f[l][r][k + 1]) f[l][r][k] = maxn, pre[l][r][k] = k;
else f[l][r][k] = f[l][r][k + 1], pre[l][r][k] = pre[l][r][k + 1];
}
} signed main() {
n = read(), m = read();
for (int i = 1; i <= m; i++)
a[i].l = read(), a[i].r = read(), a[i].c = read(), res[i] = a[i].c;
sort(res + 1, res + 1 + m);
tot = unique(res + 1, res + m + 1) - res - 1;
for (int i = 1; i <= m; i++)
a[i].c = lower_bound(res + 1, res + tot + 1, a[i].c) - res;
for (int i = n; i >= 1; i--)
for (int j = i; j <= n; j++)
update(i, j), dp(i, j);
work(1, n, 1);
cout << f[1][n][1] << '\n';
for (int i = 1; i <= n; i++) cout << ans[i] << " ";
return 0;
}

洛谷 P3592 [POI2015]MYJ的更多相关文章

  1. P3592 [POI2015]MYJ

    P3592 [POI2015]MYJ 一道比较烦的区间dp.. 昨天上课讲到了这题,然后就在lg翻到了 然后调了很久很久..... 设\(f[l][r][k]\)为区间\([l,r]\)中,最小值\( ...

  2. luogu P3592 [POI2015]MYJ

    题目链接 luogu P3592 [POI2015]MYJ 题解 区间dp 设f[l][r][k]表示区间l到r内最小值>=k的最大收益 枚举为k的位置p,那么包含p的区间答案全部是k 设h[i ...

  3. 洛谷P3582 [POI2015]KIN

    题目描述 共有\(m\)部电影,编号为\(1--m\),第\(i\)部电影的好看值为\(w[i]\).在\(n\)天之中(从\(1~n\)编号)每天会放映一部电影,第\(i\)天放映的是第\(f[i] ...

  4. BZOJ 4385 洛谷3594 POI2015 WIL-Wilcze doły

    [题解] 手残写错调了好久QAQ...... 洛谷的数据似乎比较水.. n个正整数!!这很重要 这道题是个类似two pointer的思想,外加一个单调队列维护当前区间内长度为d的子序列中元素之和的最 ...

  5. 洛谷 P3586 [POI2015]LOG

    P3586 [POI2015]LOG 题目描述 维护一个长度为n的序列,一开始都是0,支持以下两种操作:1.U k a 将序列中第k个数修改为a.2.Z c s 在这个序列上,每次选出c个正数,并将它 ...

  6. 洛谷P3588 - [POI2015]Pustynia

    Portal Description 给定一个长度为\(n(n\leq10^5)\)的正整数序列\(\{a_n\}\),每个数都在\([1,10^9]\)范围内,告诉你其中\(s\)个数,并给出\(m ...

  7. 洛谷 P3585 [POI2015]PIE

    P3585 [POI2015]PIE 题目描述 一张n*m的方格纸,有些格子需要印成黑色,剩下的格子需要保留白色.你有一个a*b的印章,有些格子是凸起(会沾上墨水)的.你需要判断能否用这个印章印出纸上 ...

  8. 洛谷P3588 [POI2015]PUS

    题面 sol:说了是线段树优化建图的模板... 就是把一整个区间的点连到一个点上,然后用那个点来连需要连一整个区间的点就可以了,就把边的条数优化成n*log(n)了 #include <queu ...

  9. 洛谷P3586 [POI2015]LOG(贪心 权值线段树)

    题意 题目链接 Sol 显然整个序列的形态对询问没什么影响 设权值\(>=s\)的有\(k\)个. 我们可以让这些数每次都被选择 那么剩下的数,假设值为\(a_i\)次,则可以\(a_i\)次被 ...

随机推荐

  1. java实现第六届蓝桥杯熊怪吃核桃

    熊怪吃核桃 题目描述 森林里有一只熊怪,很爱吃核桃.不过它有个习惯,每次都把找到的核桃分成相等的两份,吃掉一份,留一份.如果不能等分,熊怪就会扔掉一个核桃再分.第二天再继续这个过程,直到最后剩一个核桃 ...

  2. tensorflow2.0学习笔记第二章第二节

    2.2复杂度和学习率 指数衰减学习率可以先用较大的学习率,快速得到较优解,然后逐步减少学习率,使得模型在训练后期稳定指数衰减学习率 = 初始学习率 * 学习率衰减率^(当前轮数/多少轮衰减一次) 空间 ...

  3. xlua中lua对象到c#对象的转型

    lua中的类型 基础类型 #define LUA_TNIL 0 #define LUA_TBOOLEAN 1 #define LUA_TLIGHTUSERDATA 2 #define LUA_TNUM ...

  4. 学习ASP.NET Core(10)-全局日志与xUnit系统测试

    上一篇我们介绍了数据塑形,HATEOAS和内容协商,并在制器方法中完成了对应功能的添加:本章我们将介绍日志和测试相关的概念,并添加对应的功能 一.全局日志 在第一章介绍项目结构时,有提到.NET Co ...

  5. UI 小白设计常用的Website

    网址 设计师导航网址(其实这个用好了,enough) 设计导航1 设计导航2 icon 阿里巴巴Iconfont flaticons icomoon Noun Project 图片(有时候就是灵魂) ...

  6. 用python简单爬取一个网页

    1打开编辑器 2撸几行代码 import urllib.request import urllib.error def main(): askURl("http://movie.douban ...

  7. PuTTY通过SSH连接上Ubuntu20.04

    在PuTTY中连接到Ubuntu20.04大致需要几个步骤(不一定对应文本中的序号):1) 安装opensh-server (Ubuntu安装好之后 ,一般openssh-client自动已经安装好) ...

  8. 面试官:线程池如何按照core、max、queue的执行循序去执行?(内附详细解析)

    前言 这是一个真实的面试题. 前几天一个朋友在群里分享了他刚刚面试候选者时问的问题:"线程池如何按照core.max.queue的执行循序去执行?". 我们都知道线程池中代码执行顺 ...

  9. mysql字符串类型(set类型)

    集合 set  不定想项选 类似于 enum枚举,在定义时,也需要指定其已有值! 与字符串相比,优势是: 1, 也是采用 整数进行管理的!采用位运算,从第一位开始为1,逐一x2! 2, 每个集合类型8 ...

  10. wget介绍和命令总结

    参考资料: https://www.cnblogs.com/ftl1012/p/9265699.html https://www.cnblogs.com/lsdb/p/7171779.html cur ...