P1973 [NOI2011] NOI 嘉年华
思路:
先将时间进行离散化,设总时间为 \(cnt\),然后考虑求出 \(W(l,r)\),即在时间段 \([l,r]\) 内的所有节目,可以 \(n^2\) 前缀和,也可以 \(n^3\) 暴力。
然后定义 \(f_{i,j}\) 表示前 \(i\) 个时间,一号场地有 \(j\) 个节目时,二号场地最多的节目数量,则状态转移方程为:
\]
那么可以得到:
\]
则第一个问的时间复杂度为 \(O(N^3)\)。
然后再看第二个问,需要定义 \(g_{i,j}\) 表示 \(i \sim cnt\) 的时间段,一号场地有 \(j\) 个节目时,二号场地最多的节目数量,则状态转移方程类似:
\]
然后再定义 \(dp_{l,r}\) 表示若强制选 \([l,r]\) 的全部节目的局部最优解,则可以枚举左边和右边一号场有多少个进行转移:
\]
那么此时若强制选 \([l,r]\) 的答案,是 \(dp_{l,r}\) 吗?答案很明显,不是。
因为 \(f_{l-1,i}\) 和 \(g_{r+1,j}\) 只保证了 \(1 \sim l-1,r+1 \sim j\) 的局部最优,即可能会有一些活动的一端在 \([l,r]\) 内,但是另一端不在 \([l,r]\) 内,此时选这些节目可能会更优。
于是我们需要枚举一个 \([L,R]\),使得 \([L,R]\) 包含 \([l,r]\),故 \([l,r]\) 强制选的答案为:
\]
故只要我们求出 \(dp\),就可以 \(O(N^3)\) 的得到答案。
但是计算 \(dp\) 的时间复杂度为 \(O(N^4)\),且常数较大,需要优化卡常大师应该能冲过去。
注意到 \(f_{l,i}\) 和 \(g_{r,j}\) 是会随着 \(i/j\) 的增大而不增的。
此时若 \(i\) 不动,则对于 \(j\) 来说, \(i+W(l,r)+j\) 是单增的,\(f_{l,i} + g_{r,j}\) 是单降的,故 \(H(y)=\min(i+W(l,r)+j,f_{l,i} + g_{r,j})\) 是一个单峰的函数,我们需要找到其最大值。
故我们可以对 \(j\) 进行走指针,从 \(yjn\) 开始,若 \(H(j-1)\ge H(j)\),就可以令 \(j \gets j - 1\)。
这里需要证明一下在 \(i\) 增加时,\(j\) 的单峰函数只会向左平移,因为这样才可以走指针:
在 \(i\) 增加时,\(i+W(l,r)+j\) 也会增加。
而对于 \(f_{l,i}+g_{r,j}\) 不增。
故会峰点左移。
总时间复杂度是 \(O(N^3)\)。
完整代码:
#include<bits/stdc++.h>
#define Add(x,y) (x+y>=mod)?(x+y-mod):(x+y)
#define lowbit(x) x&(-x)
#define pi pair<ll,ll>
#define pii pair<ll,pair<ll,ll>>
#define iip pair<pair<ll,ll>,ll>
#define ppii pair<pair<ll,ll>,pair<ll,ll>>
#define fi first
#define se second
#define full(l,r,x) for(auto it=l;it!=r;it++) (*it)=x
#define Full(a) memset(a,0,sizeof(a))
#define open(s1,s2) freopen(s1,"r",stdin),freopen(s2,"w",stdout);
using namespace std;
typedef double db;
typedef unsigned long long ull;
typedef long long ll;
bool Begin;
const int N=205,M=410,INF=1e9;
inline ll read(){
ll x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')
f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
inline void write(ll x){
if(x<0){
putchar('-');
x=-x;
}
if(x>9)
write(x/10);
putchar(x%10+'0');
}
struct Seg{
int l,r;
int id;
}A[N];
int n,cnt,Max;
int ans[N],s[N],h[M];
int F[M][N],G[M][N],dp[M][M],W[M][M];
int get(int i,int j,int l,int r){
return min(i+W[l][r]+j,F[l][i]+G[r][j]);
}
bool End;
int main(){
// open("A.in","A.out");
n=read();
for(int i=1;i<=n;i++){
A[i].l=read(),A[i].r=A[i].l+read();
A[i].id=i;
h[++cnt]=A[i].l;
h[++cnt]=A[i].r;
}
sort(h+1,h+cnt+1);
cnt=unique(h+1,h+cnt+1)-(h+1);
for(int i=1;i<=n;i++){
A[i].l=lower_bound(h+1,h+cnt+1,A[i].l)-h;
A[i].r=lower_bound(h+1,h+cnt+1,A[i].r)-h;
}
for(int l=1;l<=cnt;l++)
for(int r=l;r<=cnt;r++)
for(int i=1;i<=n;i++)
if(l<=A[i].l&&A[i].r<=r)
W[l][r]++;
for(int i=0;i<=cnt;i++)
for(int j=0;j<=n;j++)
F[i][j]=-INF;
F[0][0]=0;
for(int i=1;i<=cnt;i++)
for(int j=0;j<=n;j++)
for(int k=0;k<i;k++)
F[i][j]=max({F[i][j],F[k][j]+W[k][i],(j>=W[k+1][i])?(F[k][j-W[k][i]]):(-INF)});
for(int i=1;i<=cnt+1;i++)
for(int j=0;j<=n;j++)
G[i][j]=-INF;
G[cnt+1][0]=0;
for(int i=cnt;i>=1;i--)
for(int j=0;j<=n;j++)
for(int k=i+1;k<=cnt+1;k++)
G[i][j]=max({G[i][j],G[k][j]+W[i][k],(j>=W[i+1][k])?(G[k][j-W[i][k]]):(-INF)});
for(int l=1;l<=cnt;l++){
for(int r=l;r<=cnt;r++){
for(int x=0,y=n;x<=n;x++){
while(y&&get(x,y-1,l,r)>=get(x,y,l,r))
y--;
dp[l][r]=max(dp[l][r],get(x,y,l,r));
}
}
}
for(int i=0;i<=n;i++)
ans[0]=max(ans[0],min(i,F[cnt][i]));
for(int i=1;i<=n;i++)
for(int L=1;L<=A[i].l;L++)
for(int R=A[i].r;R<=cnt;R++)
ans[i]=max(ans[i],dp[L][R]);
for(int i=0;i<=n;i++){
write(ans[i]);
putchar('\n');
}
cerr<<'\n'<<abs(&Begin-&End)/1048576<<"MB";
return 0;
}
P1973 [NOI2011] NOI 嘉年华的更多相关文章
- luogu P1973 [NOI2011]NOI 嘉年华 dp
LINK:NOI 嘉年华 一道质量非常高的dp题目. 考虑如何求出第一问 容易想到dp. 按照左端点排序/右端点排序状态还是很难描述. 但是我们知道在时间上肯定是一次选一段 所以就可以直接利用时间点来 ...
- 洛谷P1973 [NOI2011]Noi嘉年华(动态规划,决策单调性)
洛谷题目传送门 DP题怕是都要大大的脑洞...... 首先,时间那么大没用,直接离散化. 第一问还好.根据题意容易发现,当一堆活动的时间有大量重叠的时候,更好的办法是把它们全部安排到一边去.那么我们转 ...
- 洛谷P1973 [NOI2011]Noi嘉年华(决策单调性)
传送门 鉴于FlashHu大佬讲的这么好(而且我根本不会)我就不再讲一遍了->传送 //minamoto #include<iostream> #include<cstdio& ...
- P1973 [NOI2011]Noi嘉年华
传送门 首先可以把时间区间离散化 然后求出 $cnt[l][r]$ 表示完全在时间 $[l,r]$ 之内的活动数量 设 $f[i][j]$ 表示当前考虑到时间 $i$,第一个会场活动数量为 $j$ 时 ...
- 【BZOJ 2436】 2436: [Noi2011]Noi嘉年华 (区间DP)
2436: [Noi2011]Noi嘉年华 Description NOI2011 在吉林大学开始啦!为了迎接来自全国各地最优秀的信息学选手,吉林大学决定举办两场盛大的 NOI 嘉年华活动,分在两个不 ...
- 2436: [Noi2011]Noi嘉年华 - BZOJ
Description NOI2011 在吉林大学开始啦!为了迎接来自全国各地最优秀的信息学选手,吉林大学决定举办两场盛大的 NOI 嘉年华活动,分在两个不同的地点举办.每个嘉年华可能包含很多个活动, ...
- bzoj 2436: [Noi2011]Noi嘉年华
Description NOI2011 在吉林大学开始啦!为了迎接来自全国各地最优秀的信息学选手,吉林大学决定举办两场盛大的 NOI 嘉年华活动,分在两个不同的地点举办.每个嘉年华可能包含很多个活动, ...
- NOI2011 NOI嘉年华
http://www.lydsy.com/JudgeOnline/problem.php?id=2436 首先离散化,离散化后时间范围为[1,cnt]. 求出H[i][j],表示时间范围在[i,j]的 ...
- bzoj2436: [Noi2011]Noi嘉年华
我震惊了,我好菜,我是不是该退役(苦逼) 可以先看看代码里的注释 首先我们先考虑一下第一问好了真做起来也就这个能想想了 那么离散化时间是肯定的,看一手范围猜出是二维DP,那对于两个会场,一个放自变量, ...
- BZOJ2436 [Noi2011]Noi嘉年华 【dp】
题目链接 BZOJ2436 题解 看这\(O(n^3)\)的数据范围,可以想到区间\(dp\) 发现同一个会场的活动可以重叠,所以暴力求出\(num[l][r]\)表示离散化后\([l,r]\)的完整 ...
随机推荐
- mediaserverd
1.mediaserverd是什么 mediaserverd(/usr/sbin/mediaserverd)是被root进程launchd启动的一个后台(daemon)进程,其描述文件为com.app ...
- scala怎么退出
scala怎么退出 scala> :help //查看帮助 All commands can be abbreviated, e.g., :he instead of :help. :edit ...
- 红米K70E支付宝无指纹支付选项的解决方法
红米K70E这台手机,支付宝里无指纹支付选项,百度了一下,也没结果.自己摸索了下,终于折腾出了指纹支付. 解决方法: 在手机-设置-指纹.面部与密码-指纹解锁-指纹支付-支付宝-更新证书. 杀掉支付宝 ...
- readonly和disable的区别是什么?
Readonly和Disabled两种属性的写法如下: 1.<input type="text" name="name" value="xxx& ...
- SD-WAN中二层组网与三层组网的区别
前言 随着企业网络需求的不断增长和变化,SD-WAN作为一种现代网络技术,为企业提供了更灵活.高效的网络解决方案.在SD-WAN中,二层组网和三层组网是两种常见的部署模型,它们有着各自的特点和适用场景 ...
- 调用了这么久的JS方法是长在对象、类、值本身还是原型链上?
调用了这么久的JS方法是长在对象.类.值本身还是原型链上? JavaScript这门语言总是能带给我惊喜,在敲代码的时候习以为常的写法,退一步再看看发现自己其实对很多基操只有表面的使用,而从来没思考过 ...
- FFmpeg开发笔记(三十四)Linux环境给FFmpeg集成libsrt和librist
<FFmpeg开发实战:从零基础到短视频上线>一书的"10.2 FFmpeg推流和拉流"提到直播行业存在RTSP和RTMP两种常见的流媒体协议.除此以外,还有比较两 ...
- 全志科技A40i开发板规格书(四核ARM Cortex-A7,主频1.2GHz)
1.评估板简介 创龙科技TLA40i-EVM是一款基于全志科技A40i处理器设计的4核ARM Cortex-A7高性能低功耗国产评估板,每核主频高达1.2GHz,由核心板和评估底板组成. 评估板接口资 ...
- AT_abc317_f 题解
调了一小时结果发现爆 long long 了. 考虑数位 dp,具体来说,设计状态 \(dp_{i,r_1,r_2,r_3,mx_1,mx_2,mx3_,c_1,c_2,c_3}\) 表示当前考虑到第 ...
- Python数据分析代码示例
数据清洗 在进行数据分析之前,通常需要对原始数据进行清洗,即处理缺失值.异常值.重复值等问题. 下面是一个数据清洗的示例代码: import pandas as pd # 读取原始数据 data = ...