洛谷题目传送门

DP题怕是都要大大的脑洞。。。。。。

首先,时间那么大没用,直接离散化。

第一问还好。根据题意容易发现,当一堆活动的时间有大量重叠的时候,更好的办法是把它们全部安排到一边去。那么我们转移的时候也肯定是要一块一块地转移啦。

设\(tot_{l,r}\)为完全被包含在\(l-r\)时间内活动总数,直接\(O(n^3)\)暴力求就好了。

设\(pre_{i,j}\)为时间\(1-i\)内一边选\(j\)个时,另一边能选的最大值。枚举一块转移的话,我们的方程应该写成这样:

\[pre_ {i,j}=\max\limits_{k=1}^i\{pre_ {k,j}+tot_{k,i},pre _{k,j-tot _{k,i}}\}
\]

(显然两种情况都要考虑)

然后答案就是\(\max\limits_{j=1}^n\{\min(pre_{m,j},j)\}\)啦(\(m\)为离散化后的时间总长,不会超过\(2n\))

这个数组为什么要叫\(pre\)呢?这是个前缀DP值。为了第二问,我们还要做个后缀DP,\(suf_{i,j}\)表示时间\(i-m\)内一边选\(j\)个时,另一边能选的最大值,跟\(pre\)几乎一样的转移,也是\(O(n^3)\)的。

对于第二问,我们显然可以肯定\(s_i-t_i\)之内的活动都被一边选走了。至于\(s_i\)之前和\(t_i\)以后选了多少,我们也只好枚举。设\(f_{l,r}\)为一边强制选\(l-r\)之间所有活动时最优的最小值,假定这一边在前面选了\(x\)个,在后面选了\(y\)个,另一边最多能选多少也就知道了,有方程

\[f_{l,r}=\max\limits_{x=1}^m\max\limits_{y=1}^m\{\min(x+tot_{l,r}+y,pre_{l,x}+suf_{r,y})\}
\]

然后第\(i\)个的答案就是\(f_{s_i,t_i}\)么?注意千万别掉入这个误区!\(pre\)和\(suf\)只是保证了局部最优,而没有保证全局最优。要说人话的话,就是可能有一个活动跨过了\(s_i\),然而\(f_{s_i,t_i}\)并没有统计到它,只有扩大强制选的区间使得能够包含它,才能统计到最优解。于是需要枚举强制选区间了,\(ans_i=\max\limits_{l=1}^{s_i}\max\limits_{r=t_i}^m\{f_{l,r}\}\)

这样的话,整个\(f\)都必须要算出来,上面的枚举算法就变成\(O(n^4)\)了,跑不动。

点开标签发现有单调队列?!蒟蒻就往单调性上面想了想,于是就有了一个结论:设枚举\(x\)时有一个使答案最优的\(y\),那么当\(x\)增大时,如果\(y\)也增大那么答案不会更优。观察上面那个式子\(\min(x+tot_{l,r}+y,pre_{l,x}+suf_{r,y})\),那么因为\(pre,suf\)都是递减的,所以很显然我们不能让\(x,y\)变大而\(pre,suf\)变小。

于是,实现的时候,只要把\(y\)从大往小扫了,并不需要什么单调队列来维护它。

#include<cstdio>
#include<algorithm>
#define RG register
#define R RG int
#define G c=getchar()
#define Upd(A,L,R) {chkmx(A[i][j],A[k][j]+tot[L][R]); \
if(j>=tot[L][R])chkmx(A[i][j],A[k][j-tot[L][R]]);}
#define Calc(y) min(x+tot[l][r]+y,pre[l][x]+suf[r][y])
using namespace std;
const int N=209,M=409,INF=1e9;
int s[N],t[N],b[M],tot[M][M],pre[M][N],suf[M][N],f[M][M];
inline int in(){
RG char G;
while(c<'-')G;
R x=c&15;G;
while(c>'-')x=x*10+(c&15),G;
return x;
}
inline int min(R x,R y){return x<y?x:y;}
inline void chkmx(R&x,R y){if(x<y)x=y;}
int main(){
R n=in(),m=0,i,j,k,l,r,x,y,p0,p1,ans;
for(i=1;i<=n;++i){
b[++m]=s[i]=in();
b[++m]=t[i]=in()+s[i];
}
sort(b+1,b+m+1);//离散化
m=unique(b+1,b+m+1)-b-1;
for(i=1;i<=n;++i){
s[i]=lower_bound(b+1,b+m+1,s[i])-b;
t[i]=lower_bound(b+1,b+m+1,t[i])-b;
for(l=1;l<=s[i];++l)//tot暴力求
for(r=m;r>=t[i];--r)++tot[l][r];
}
for(i=1;i<=m;++i)//注意初始化
for(j=1;j<=n;++j)pre[i][j]=suf[i][j]=-INF;
for(i=1;i<=m;++i)
for(j=0;j<=tot[1][i];++j)
for(k=1;k<=i;++k)Upd(pre,k,i);
for(i=m;i;--i)//转移很相似,搞了个宏定义
for(j=0;j<=tot[i][m];++j)
for(k=i;k<=m;++k)Upd(suf,i,k);
for(l=1;l<=m;++l)
for(r=l+1;r<=m;++r)
for(y=n,x=0;x<=n;++x){
p0=Calc(y);//p0为最优决策,p1为当前决策
while(y&&p0<=(p1=Calc(y-1)))p0=p1,--y;
chkmx(f[l][r],Calc(y));
}
ans=0;
for(j=1;j<=n;++j)chkmx(ans,min(pre[m][j],j));
printf("%d\n",ans);
for(i=1;i<=n;++i){
ans=0;
for(l=1;l<=s[i];++l)
for(r=m;r>=t[i];--r)chkmx(ans,f[l][r]);
printf("%d\n",ans);
}
return 0;
}

洛谷P1973 [NOI2011]Noi嘉年华(动态规划,决策单调性)的更多相关文章

  1. 洛谷P1973 [NOI2011]Noi嘉年华(决策单调性)

    传送门 鉴于FlashHu大佬讲的这么好(而且我根本不会)我就不再讲一遍了->传送 //minamoto #include<iostream> #include<cstdio& ...

  2. luogu P1973 [NOI2011]NOI 嘉年华 dp

    LINK:NOI 嘉年华 一道质量非常高的dp题目. 考虑如何求出第一问 容易想到dp. 按照左端点排序/右端点排序状态还是很难描述. 但是我们知道在时间上肯定是一次选一段 所以就可以直接利用时间点来 ...

  3. 洛谷P3515 [POI2011]Lightning Conductor(决策单调性)

    题意 已知一个长度为n的序列a1,a2,...,an. 对于每个1<=i<=n,找到最小的非负整数p满足 对于任意的j, aj < = ai + p - sqrt(abs(i-j)) ...

  4. 洛谷 P3515 [ POI 2011 ] Lightning Conductor —— 决策单调性DP

    题目:https://www.luogu.org/problemnew/show/P3515 决策单调性... 参考TJ:https://www.cnblogs.com/CQzhangyu/p/725 ...

  5. P1973 [NOI2011]Noi嘉年华

    传送门 首先可以把时间区间离散化 然后求出 $cnt[l][r]$ 表示完全在时间 $[l,r]$ 之内的活动数量 设 $f[i][j]$ 表示当前考虑到时间 $i$,第一个会场活动数量为 $j$ 时 ...

  6. 洛谷P3724 [AH2017/HNOI2017]大佬(决策单调性)

    传送门 这个思路很妙诶->这里 以下为了方便,我把自信说成血量好了 虽然表面上看起来每一天有很多种选择,然而我们首先要保证的是不死,然后考虑不死的情况下最多能拿出多少天来进行其他操作.不死可以d ...

  7. 【BZOJ 2436】 2436: [Noi2011]Noi嘉年华 (区间DP)

    2436: [Noi2011]Noi嘉年华 Description NOI2011 在吉林大学开始啦!为了迎接来自全国各地最优秀的信息学选手,吉林大学决定举办两场盛大的 NOI 嘉年华活动,分在两个不 ...

  8. bzoj 2436: [Noi2011]Noi嘉年华

    Description NOI2011 在吉林大学开始啦!为了迎接来自全国各地最优秀的信息学选手,吉林大学决定举办两场盛大的 NOI 嘉年华活动,分在两个不同的地点举办.每个嘉年华可能包含很多个活动, ...

  9. 2436: [Noi2011]Noi嘉年华 - BZOJ

    Description NOI2011 在吉林大学开始啦!为了迎接来自全国各地最优秀的信息学选手,吉林大学决定举办两场盛大的 NOI 嘉年华活动,分在两个不同的地点举办.每个嘉年华可能包含很多个活动, ...

随机推荐

  1. 将当前的Ubuntu系统封装成为可以安装(发布)的iso镜像

    将当前的Ubuntu系统封装成为可以安装(发布)的iso镜像 在使用以上方法安装依赖的时候xresprobe 会找不到安装地址,采用下面的方式: Package xresprobe is not in ...

  2. Spring Boot 2.0(七):Spring Boot 如何解决项目启动时初始化资源

    在我们实际工作中,总会遇到这样需求,在项目启动的时候需要做一些初始化的操作,比如初始化线程池,提前加载好加密证书等.今天就给大家介绍一个 Spring Boot 神器,专门帮助大家解决项目启动初始化资 ...

  3. 编写一个供浏览器端使用的NPM包

    此文已由作者吴维伟授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 在编写程序时,总会有一些代码是我们不愿意一遍又一遍重复地去写的,比如一些UI或交互相似组件,或是一些相似的流 ...

  4. HTTP Error 500.22 - Internal Server Error 错误解决方案

    1. 首先进入IIS ,配置IIS 应用程序池的.Net Framework版本 2. 点击左侧应用程序池,再单机右侧设置,选择版本 3. 设置为经典模式 如若遇到以下错误: 解决方案:删除confi ...

  5. BugkuCTF 域名解析

    前言 写了这么久的web题,算是把它基础部分都刷完了一遍,以下的几天将持续更新BugkuCTF WEB部分的题解,为了不影响阅读,所以每道题的题解都以单独一篇文章的形式发表,感谢大家一直以来的支持和理 ...

  6. 网站每日PV/IP统计/总带宽/URL统计脚本分享(依据网站访问日志)

    在平时的运维工作中,我们运维人员需要清楚自己网站每天的总访问量.总带宽.ip统计和url统计等.虽然网站已经在服务商那里做了CDN加速,所以网站流量压力都在前方CDN层了像每日PV,带宽,ip统计等数 ...

  7. Python下操作Memcache/Redis/RabbitMQ说明

    一.MemcacheMemcache是一套分布式的高速缓存系统,由LiveJournal的Brad Fitzpatrick开发,但目前被许多网站使用以提升网站的访问速度,尤其对于一些大型的.需要频繁访 ...

  8. 牛客多校第二场A run(基础DP)

    链接:https://www.nowcoder.com/acm/contest/140/A来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 131072K,其他语言2621 ...

  9. mysql 多列索引的生效规则,生成1000w数据的存储过程

    https://www.cnblogs.com/codeAB/p/6387148.html

  10. 【个人阅读作业】软件工程M1/M2总结

    链接:”看<快速软件开发>的五个问题“ http://www.cnblogs.com/leiyy/p/4027759.html 一.较为明白的问题 1. 在文章的第一个关于Square_T ...