热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:dpbzoj2436noi2011noi嘉年华

https://www.lydsy.com/JudgeOnline/problem.php?id=2436只会

https://www.lydsy.com/JudgeOnline/problem.php?id=2436

只会(mathcal O(n^5))dp怎么办

首先必要的离散化以及预处理一下区间([i,j])的线段数量(num[i][j])

注意线段是左闭右开的

(f[i][j])为在([1, i])中A拿了(j)个B最多拿(f[i][j])个 (状态设定的时候

转移枚举(k)

[
f[i][j] = maxleft { f[k][j] + num[k][i],f[k][j-num[k][i]]
ight }
]


同理(g[i][j])为在([i,infty))中A拿了(j)个B最多拿(g[i][j])

转移类似

此部分复杂度(mathcal O(n^3))

(dp[i][j])为强制A选([i,j])的最优答案

转移将(f,g,num)三部分合并在一起

枚举A在(f,g)分别选了(x,y)

感性理解可知随着(x)的单增(y)不减

因此复杂度(mathcal O(n^3))

总复杂度也是(mathcal O(n^3))

在状态比较维数比较多的时候可以考虑利用增加辅助的(dp)数组来降低复杂度

#include
#define fo(i, n) for(int i = 1; i <= (n); i ++)
#define out(x) cerr <<#x <<" = " <n"
using namespace std;
// by piano
template<typename tp> inline void read(tp &x) {
x = 0; char c = getchar(); bool f = 0;
for(; c <&#39;0&#39; || c > &#39;9&#39;; f |= (c == &#39;-&#39;), c = getchar());
for(; c >= &#39;0&#39; && c <= &#39;9&#39;; x = (x <<3) + (x <<1) + c - &#39;0&#39;, c = getchar());
if(f) x = -x;
}
const int N = 1111;
struct NODE {
int l, r, id;
}p[N];
int f[N][N], g[N][N], num[N][N], dp[N][N], pcnt[N][N], ans[N];
int n, x[N], cnt = 0;
inline bool chkmax(int &x, int y) {
return x 1
: 0;
}
inline bool cmp(NODE a, NODE b) {
return (a.l }
#define cal(i, j, x, y) (max(min(x + y + num[i][j], f[i][x] + g[j][y]), min(x + y, f[i][x] + g[j][y] + num[i][j])))
main(void) {
read(n);
for(int i = 1; i <= n; i ++) {
read(p[i].l); read(p[i].r); p[i].r += p[i].l;
x[++ cnt] = p[i].l; x[++ cnt]= p[i].r; p[i].id = i;
}
sort(p + 1, p + n + 1, cmp);
sort(x + 1, x + cnt + 1);
cnt = unique(x + 1, x + cnt + 1) - x - 1;
for(int i = 1; i <= n; i ++) {
p[i].l = lower_bound(x + 1, x + cnt + 1, p[i].l) - x;
p[i].r = lower_bound(x + 1, x + cnt + 1, p[i].r) - x;
++ pcnt[p[i].l][p[i].r];
}
memset(num, 0, sizeof num);
for(int len = 1; len <= cnt; len ++) {
for(int l = 1; l <= cnt; l ++) {
int r = l + len - 1; if(r > cnt) break;
num[l][r] = pcnt[l][r] + num[l + 1][r] + num[l][r - 1] - num[l + 1][r - 1];
}
}
for(int i = 1; i <= cnt; i ++)
for(int j = 1; j <= n; j ++)
f[i][j] = g[i][j] = -6666;
f[0][0] = 0;
for(int i = 1; i <= cnt; i ++) {
for(int j = 0; j <= num[1][i]; j ++) {
chkmax(f[i][j], f[i - 1][j]);
for(int k = 1; k chkmax(f[i][j], f[k][j] + num[k][i]);
if(j - num[k][i] >= 0)
chkmax(f[i][j], f[k][j - num[k][i]]);
}
}
}
for(int j = 0; j <= n; j ++)
chkmax(ans[0], min(j, f[cnt][j]));
g[cnt + 1][0] = 0;
for(int i = cnt; i >= 1; i --) {
for(int j = 0; j <= num[i][cnt]; j ++) {
chkmax(g[i][j], g[i + 1][j]);
for(int k = cnt; k > i; k --) {
chkmax(g[i][j], g[k][j] + num[i][k]);
if(j - num[k][i] >= 0)
chkmax(g[i][j], g[k][j - num[i][k]]);
}
}
}
for(int i = 1; i <= cnt; i ++) {
for(int j = i + 1; j <= cnt; j ++) {
for(int x = 0, y = n; x <= n && y >= 0; x ++) {
while(y) {
int sb = cal(i, j, x, y - 1);
int sn = cal(i, j, x, y);
if(sb >= sn)
-- y;
else break;
}
chkmax(dp[i][j], cal(i, j, x, y));
}
}
}
for(int i = 1; i <= n; i ++)
for(int l = 1; l <= p[i].l; l ++)
for(int r = p[i].r; r <= cnt; r ++) {
chkmax(ans[p[i].id], dp[l][r]);
}
for(int i = 0; i <= n; i ++)
cout <"
";
}


推荐阅读
  • 火星商店问题:线段树分治与持久化Trie树的应用
    本题涉及编号为1至n的火星商店,每个商店有一个永久商品价值v。操作包括每天在指定商店增加一个新商品,以及查询某段时间内某些商店中所有商品(含永久商品)与给定密码值的最大异或结果。通过线段树分治和持久化Trie树来高效解决此问题。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 本文探讨了如何在模运算下高效计算组合数C(n, m),并详细介绍了乘法逆元的应用。通过扩展欧几里得算法求解乘法逆元,从而实现除法取余的计算。 ... [详细]
  • Splay Tree 区间操作优化
    本文详细介绍了使用Splay Tree进行区间操作的实现方法,包括插入、删除、修改、翻转和求和等操作。通过这些操作,可以高效地处理动态序列问题,并且代码实现具有一定的挑战性,有助于编程能力的提升。 ... [详细]
  • 题目Link题目学习link1题目学习link2题目学习link3%%%受益匪浅!-----&# ... [详细]
  • 本文详细探讨了VxWorks操作系统中双向链表和环形缓冲区的实现原理及使用方法,通过具体示例代码加深理解。 ... [详细]
  • Linux设备驱动程序:异步时间操作与调度机制
    本文介绍了Linux内核中的几种异步延迟操作方法,包括内核定时器、tasklet机制和工作队列。这些机制允许在未来的某个时间点执行任务,而无需阻塞当前线程,从而提高系统的响应性和效率。 ... [详细]
  • Explore how Matterverse is redefining the metaverse experience, creating immersive and meaningful virtual environments that foster genuine connections and economic opportunities. ... [详细]
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • 本实验主要探讨了二叉排序树(BST)的基本操作,包括创建、查找和删除节点。通过具体实例和代码实现,详细介绍了如何使用递归和非递归方法进行关键字查找,并展示了删除特定节点后的树结构变化。 ... [详细]
  • 文件描述符、文件句柄与打开文件之间的关联解析
    本文详细探讨了文件描述符、文件句柄和打开文件之间的关系,通过具体示例解释了它们在操作系统中的作用及其相互影响。 ... [详细]
  • 本文详细介绍了C语言中链表的两种动态创建方法——头插法和尾插法,包括具体的实现代码和运行示例。通过这些内容,读者可以更好地理解和掌握链表的基本操作。 ... [详细]
  • 本教程涵盖OpenGL基础操作及直线光栅化技术,包括点的绘制、简单图形绘制、直线绘制以及DDA和中点画线算法。通过逐步实践,帮助读者掌握OpenGL的基本使用方法。 ... [详细]
  • 本题涉及一棵由N个节点组成的树(共有N-1条边),初始时所有节点均为白色。题目要求处理两种操作:一是改变某个节点的颜色(从白变黑或从黑变白);二是查询从根节点到指定节点路径上的第一个黑色节点,若无则输出-1。 ... [详细]
  • 本文探讨了《魔兽世界》中红蓝两方阵营在备战阶段的策略与实现方法,通过代码展示了双方如何根据资源和兵种特性进行战士生产。 ... [详细]
author-avatar
忧伤玫瑰coco_873
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有