题解

一道神奇的dp

我们发现关于两个东西的记录很难办,但是我们发现在固定时间区间内,如果A场地举办的活动数是一定的,那么B场地肯定举办的活动越多越好

我们预处理一个\(num[i][j]\)表示时间区间\([i,j]\)有多少个活动会在这个区间里举办(被区间完整包含)

\(pre[i][x]\)表示\([1,i]\)的时间内,A场地举办了x个活动,B场地最多能举办多少活动

这是一个\(n^3\)的dp

转移是

\(pre[i][x] = min(pre[j][x - num[i + 1][j]],pre[j][x] + num[i + 1][j])\)就是枚举一段区间放在A场地还是B场地

第一个答案就是对于每个i的\(min(pre[tot][x],i)\)的最大值

后面的答案相当于处理出\(f[i][j]\)这段区间被A占用,活动最少场地值最大是多少

然后对于\(f[i][j]\)统计成所有\(s <= i && j <= t\)的\(f[s][t]\)的最大值

\(f[i][j] = min(pre[i - 1][x] + suf[j + 1][y],x + y + num[i][j])\)

这是\(n^4\)的

但是如果从小到大枚举x,y的最优解是递减的,就是\(n^3\)的

代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <set>
#include <cmath>
#include <bitset>
#define enter putchar('\n')
#define space putchar(' ')
//#define ivorysi
#define pb push_back
#define MAXN 100005
#define mo 974711
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 - '0' + c;
c = getchar();
}
res = res * f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) out(x / 10);
putchar('0' + x % 10);
}
int N,val[505],tot,pre[405][205],suf[405][205],num[405][405],f[405][405];
pii S[205]; void Init() {
read(N);
int x,y;
for(int i = 1 ; i <= N ; ++i) {
read(x);read(y);y = x + y - 1;
S[i] = mp(x,y);
val[++tot] = x;val[++tot] = y;
}
sort(val + 1,val + tot + 1);
tot = unique(val + 1,val + tot + 1) - val - 1;
for(int i = 1 ; i <= N ; ++i) {
S[i].fi = lower_bound(val + 1,val + tot + 1,S[i].fi) - val;
S[i].se = lower_bound(val + 1,val + tot + 1,S[i].se) - val;
}
for(int i = 1 ; i <= tot ; ++i) {
for(int j = i ; j <= tot ; ++j) {
for(int k = 1 ; k <= N ; ++k) {
if(S[k].fi >= i && S[k].se <= j) num[i][j]++;
}
}
}
} void Solve() {
for(int k = 0 ; k <= tot + 1; ++k) {
for(int i = 0 ; i <= N ; ++i) {
pre[k][i] = suf[k][i] = -1000000000;
}
}
pre[0][0] = 0;
for(int k = 1 ; k <= tot ; ++k) {
for(int j = 0 ; j < k ; ++j) {
for(int i = 0 ; i <= N ; ++i) {
pre[k][i] = max(pre[j][i] + num[j + 1][k],pre[k][i]);
if(i >= num[j + 1][k]) pre[k][i] = max(pre[k][i],pre[j][i - num[j + 1][k]]);
}
}
}
suf[tot + 1][0] = 0;
for(int k = tot ; k >= 1 ; --k) {
for(int j = tot + 1 ; j > k ; --j) {
for(int i = 0 ; i <= N ; ++i) {
suf[k][i] = max(suf[k][i],suf[j][i] + num[k][j - 1]);
if(i >= num[k][j - 1]) suf[k][i] = max(suf[k][i],suf[j][i - num[k][j - 1]]);
}
}
}
int ans = 0;
for(int i = 1 ; i <= N ; ++i) {
ans = max(ans,min(i,pre[tot][i]));
}
out(ans);enter;
for(int i = 1 ; i <= tot ; ++i) {
for(int j = i ; j <= tot ; ++j) {
int y = N;
for(int x = 0 ; x <= N ; ++x) {
if(pre[i - 1][x] < 0) break;
while(y > 0 && min(x + y + num[i][j],pre[i - 1][x] + suf[j + 1][y])
<= min(x + y - 1 + num[i][j],pre[i - 1][x] + suf[j + 1][y - 1])) --y;
f[i][j] = max(f[i][j],min(x + y + num[i][j],pre[i - 1][x] + suf[j + 1][y]));
}
}
}
for(int i = 1 ; i <= tot ; ++i) {
for(int j = tot ; j >= 1 ; --j) {
f[i][j] = max(f[i][j + 1],f[i][j]);
}
}
for(int i = 1 ; i <= tot ; ++i) {
for(int j = 1 ; j <= tot ; ++j) {
f[i][j] = max(f[i][j],f[i - 1][j]);
}
}
for(int i = 1 ; i <= N ; ++i) {
out(f[S[i].fi][S[i].se]);enter;
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Init();
Solve();
}

【LOJ】#2446. 「NOI2011」 NOI 嘉年华的更多相关文章

  1. LOJ#2444. 「NOI2011」阿狸的打字机

    题目描述 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有 \(28\) 个按键,分别印有 \(26\) 个小写英文字母和 B . P 两个字母. 经阿狸研究发现,这个打字机是 ...

  2. Loj #2192. 「SHOI2014」概率充电器

    Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...

  3. Loj #3096. 「SNOI2019」数论

    Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...

  4. Loj #3093. 「BJOI2019」光线

    Loj #3093. 「BJOI2019」光线 题目描述 当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收. 设对于任意 \(x\),有 \(x\t ...

  5. Loj #3089. 「BJOI2019」奥术神杖

    Loj #3089. 「BJOI2019」奥术神杖 题目描述 Bezorath 大陆抵抗地灾军团入侵的战争进入了僵持的阶段,世世代代生活在 Bezorath 这片大陆的精灵们开始寻找远古时代诸神遗留的 ...

  6. Loj #2542. 「PKUWC2018」随机游走

    Loj #2542. 「PKUWC2018」随机游走 题目描述 给定一棵 \(n\) 个结点的树,你从点 \(x\) 出发,每次等概率随机选择一条与所在点相邻的边走过去. 有 \(Q\) 次询问,每次 ...

  7. Loj #3059. 「HNOI2019」序列

    Loj #3059. 「HNOI2019」序列 给定一个长度为 \(n\) 的序列 \(A_1, \ldots , A_n\),以及 \(m\) 个操作,每个操作将一个 \(A_i\) 修改为 \(k ...

  8. Loj #3056. 「HNOI2019」多边形

    Loj #3056. 「HNOI2019」多边形 小 R 与小 W 在玩游戏. 他们有一个边数为 \(n\) 的凸多边形,其顶点沿逆时针方向标号依次为 \(1,2,3, \ldots , n\).最开 ...

  9. Loj #3055. 「HNOI2019」JOJO

    Loj #3055. 「HNOI2019」JOJO JOJO 的奇幻冒险是一部非常火的漫画.漫画中的男主角经常喜欢连续喊很多的「欧拉」或者「木大」. 为了防止字太多挡住漫画内容,现在打算在新的漫画中用 ...

随机推荐

  1. python中__init__()、__new__()、__call__()、__del__()用法

    关于__new__()的用法参考: http://www.myhack58.com/Article/68/2014/48183.htm 正文: 一.__new__()的用法: __new__()是在新 ...

  2. JVM 体系结构介绍

    JVM是Java的一大利器.它可以屏蔽各个计算机平台相关软件和硬件之间的差异.把平台相关的耦合统一工作交由JVM的实现者. JVM(Java 虚拟机),它通过模拟一个计算机来达到一个计算机所拥有的计算 ...

  3. UITableViewCell在非Nib及Cell重用下设置CellStyle

    在UITableViewController(实现了UITableViewDataSource)下需要实现 - (UITableViewCell *)tableView:(UITableView *) ...

  4. classpath 及读取 properties 文件

    java代码中获取项目的静态文件,如获取 properties 文件内容是必不可少的. Spring 下只需要通过 @Value 获取配置文件值 <!-- 资源文件--> <util ...

  5. NCPC2016-A-ArtWork

    题目描述 A template for an artwork is a white grid of n × m squares. The artwork will be created by pain ...

  6. bzoj千题计划141:bzoj3532: [Sdoi2014]Lis

    http://www.lydsy.com/JudgeOnline/problem.php?id=3532 如果没有字典序的限制,那么DP拆点最小割即可 加上字典序的限制: 按c从小到大枚举最小割边集中 ...

  7. python核心编程笔记——Chapter7

    Chapter7.映像和集合类型 最近临到期末,真的被各种复习,各种大作业缠住,想想已经荒废了python的学习1个月了.现在失去了昔日对python的触觉和要写简洁优雅代码的感觉,所以临到期末毅然继 ...

  8. 连接mysql提示Establishing SSL connection without server's identity verification is not recommended错误

    Establishing SSL connection without server's identity verification is not recommended. According to ...

  9. 【leetcode 简单】 第七十题 有效的字母异位词

    给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的一个字母异位词. 示例 1: 输入: s = "anagram", t = "nagaram" ...

  10. F - Number of Connected Components UVALive - 7638 (并查集 + 思维)

    题目链接:https://cn.vjudge.net/contest/275589#problem/F 题目大意:就是给你n个数,如果说两个数之间的gcd!=1,那么就将这两个点连起来,问你最终这些点 ...