Description

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

现在嘉年华活动的组织者小安一共收到了 n个活动的举办申请,其中第 i 个活动的起始时间为 Si,活动的持续时间为Ti。这些活动都可以安排到任意一个嘉年华的会场,也可以不安排。

小安通过广泛的调查发现,如果某个时刻,两个嘉年华会场同时有活动在进行(不包括活动的开始瞬间和结束瞬间),那么有的选手就会纠结于到底去哪个会场,从而变得不开心。所以,为了避免这样不开心的事情发生,小安要求不能有两个活动在两个会场同时进行(同一会场内的活动可以任意进行)。

另外,可以想象,如果某一个嘉年华会场的活动太少,那么这个嘉年华的吸引力就会不足,容易导致场面冷清。所以小安希望通过合理的安排,使得活动相对较少的嘉年华的活动数量最大。

此外,有一些活动非常有意义,小安希望能举办,他希望知道,如果第i 个活动必须举办(可以安排在两场嘉年华中的任何一个),活动相对较少的嘉年华的活动数量的最大值。

Solution

正解:DP+单调性优化

第一问非常简单,有两个嘉年华,所以要固定一个,设 \(f[i][j]\) 表示目前在 \(i\) 这个活动的右端点上,选择了\(j\)个放入第一个嘉年华,第二个嘉年华的最大活动数量

转移有两种:枚举 \(k<i\),\(k\)到\(i\)之间活动的要不给第一个嘉年华要不给第二个,所以预处理一个 \(c[i][j]\) 表示 \(i\)到\(j\)时间段内的活动数量,就可以 \(O(1)\) 转移了

第二问可以直接用第一问的DP数组,同理再求一个后缀的 \(f\) 数组,设为 \(g\).

那么如果是固定时间在 \(i,j\) 之间的活动的话,那么就是从 \(f[i-1][a]+g[j+1][b]+c[i][j]\) 中决策了,枚举\(a,b\),讨论\(c[i][j]\)分给第一个嘉年华,分给第二个嘉年华即可.

这样做的话是 \(O(n^5)\),所以只需要离线询问,设 \(dp[i][j]\) 表示上面说的:固定时间在 \(i,j\) 之间的活动,两个嘉年华中的最小值的最大值为多少

回答询问就可以 O\((n^2)\) 了.

注意:预处理 \(dp\) 数组是 \(O(n^4)\),但是限制上界的话,暴力是可以过的.

正解是 \(O(n^3)\) 预处理的,利用一个单调性:

假设枚举\(a\)为左边分给第一个嘉年华的活动数量,\(b\)为右边分给第一个嘉年华的

那么 \(a\)增大,\(b\)只能减小,所以可以单调指针扫描 \(b\),复杂度就降下来了.

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define RG register
#define il inline
#define iter iterator
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
const int N=405;
int n,B[N],num=0,c[N][N],f[N][N],g[N][N],dp[N][N],m;
struct sub{int l,r;}e[N];
void work()
{
scanf("%d",&n);m=n;
for(int i=1;i<=n;i++){
scanf("%d%d",&e[i].l,&e[i].r);
e[i].r=e[i].l+e[i].r-1;
B[++num]=e[i].l;B[++num]=e[i].r;
}
sort(B+1,B+num+1);
num=unique(B+1,B+num+1)-B-1;
for(int i=1;i<=m;i++){
e[i].l=lower_bound(B+1,B+num+1,e[i].l)-B;
e[i].r=lower_bound(B+1,B+num+1,e[i].r)-B;
for(int j=e[i].l;j>=1;j--)
for(int k=e[i].r;k<=num;k++)c[j][k]++;
}
memset(f,-127/3,sizeof(f));
memset(g,-127/3,sizeof(g));
n=num;
f[0][0]=0;
for(int i=1;i<=n;i++)
for(int j=0;j<=c[1][i];j++){
f[i][j]=f[i-1][j];
for(int k=0;k<i;k++){
f[i][j]=Max(f[i][j],f[k][j]+c[k+1][i]);
if(j>=c[k+1][i])f[i][j]=Max(f[i][j],f[k][j-c[k+1][i]]);
}
}
g[n+1][0]=0;
for(int i=n;i>=1;i--)
for(int j=0;j<=c[i][n];j++){
g[i][j]=g[i+1][j];
for(int k=i+1;k<=n+1;k++){
g[i][j]=Max(g[i][j],g[k][j]+c[i][k-1]);
if(j>=c[i][k-1])g[i][j]=Max(g[i][j],g[k][j-c[i][k-1]]);
}
}
int ans=0;
for(int i=1;i<=n;i++)
for(int j=0;j<=i;j++)
ans=max(ans,min(f[i][j],j));
printf("%d\n",ans);
int v1,v2,b;
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++){
b=c[j+1][n];
for(RG int a=0;a<=c[1][i-1];a++){
for(;b>=0;b--){
v1=min(a+b,f[i-1][a]+g[j+1][b]+c[i][j]);
v1=max(v1,min(a+b+c[i][j],f[i-1][a]+g[j+1][b]));
v2=min(a+b-1,f[i-1][a]+g[j+1][b-1]+c[i][j]);
v2=max(v2,min(a+b+c[i][j]-1,f[i-1][a]+g[j+1][b-1]));
if(v1>v2)break;
}
dp[i][j]=Max(dp[i][j],v1);
}
}
for(int i=1;i<=m;i++){
ans=0;
for(int j=e[i].l;j>=1;j--)
for(int k=e[i].r;k<=n;k++)
ans=max(ans,dp[j][k]);
printf("%d\n",ans);
}
} int main()
{
freopen("pp.in","r",stdin);
freopen("pp.out","w",stdout);
work();
return 0;
}

bzoj 2436: [Noi2011]Noi嘉年华的更多相关文章

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

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

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

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

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

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

  4. NOI2011 NOI嘉年华

    http://www.lydsy.com/JudgeOnline/problem.php?id=2436 首先离散化,离散化后时间范围为[1,cnt]. 求出H[i][j],表示时间范围在[i,j]的 ...

  5. bzoj2436: [Noi2011]Noi嘉年华

    我震惊了,我好菜,我是不是该退役(苦逼) 可以先看看代码里的注释 首先我们先考虑一下第一问好了真做起来也就这个能想想了 那么离散化时间是肯定的,看一手范围猜出是二维DP,那对于两个会场,一个放自变量, ...

  6. 洛谷P1973 [NOI2011]Noi嘉年华(动态规划,决策单调性)

    洛谷题目传送门 DP题怕是都要大大的脑洞...... 首先,时间那么大没用,直接离散化. 第一问还好.根据题意容易发现,当一堆活动的时间有大量重叠的时候,更好的办法是把它们全部安排到一边去.那么我们转 ...

  7. BZOJ2436 [Noi2011]Noi嘉年华 【dp】

    题目链接 BZOJ2436 题解 看这\(O(n^3)\)的数据范围,可以想到区间\(dp\) 发现同一个会场的活动可以重叠,所以暴力求出\(num[l][r]\)表示离散化后\([l,r]\)的完整 ...

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

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

  9. cogs 1377. [NOI2011] NOI嘉年华 (dp

    题意:给你n个活动的起止时间,要你从中选一些活动在2个会场安排(不能有两个活动在两个会场同时进行),使活动较少的会场活动数最大,以及在某个活动必须选择的前提下,求该答案. 思路:由于n很小,时间很大, ...

随机推荐

  1. 第一次作业:我与CS的缘分

    "既然选择了远方,便只顾风雨兼程"   --汪国真 一.结缘计算机 1.1初识计算机 当第一次看到这个作业题目的时候,我的思虑不禁回到了小时候那个对这个世界的一切充满兴趣的纯真年代 ...

  2. Software Engineering-HW2

    title: Software Engineering-HW2 date: 2017-09-21 10:35:47 tags: HW --- 题目描述 从<构建之法>第一章的 " ...

  3. 项目Beta冲刺Day7

    项目进展 李明皇 今天解决的进度 部分数据传递和使用逻辑测试 林翔 今天解决的进度 服务器端查看个人发布的action,修改已发布消息状态的action,仍在尝试使用第三方云存储功能保存图片 孙敏铭 ...

  4. IOS UITextView自适应高度

    LOFTER app需要实现了一个类似iPhone短信输入框的功能,它的功能其实蛮简单,就是:[UITextView的高度随着内容高度的变化而变化].实现思路应该是: 在UITextView的text ...

  5. Struts2之配置文件中Action的详细配置

    在Struts2之配置一文中,我们知道一个struts配置文件可以分为三部分:常量配置    包含其他配置文件的配置    Action配置  . 这其中 常量配置  和 包含其他配置文件的配置  二 ...

  6. OO前三次作业总结

    一.第一次作业 1.程序设计分析 ![img](s1.ax1x.com/2018/04/02/CSgoSU.png) 图1 第一次作业类图 ![name](https://images2018.cnb ...

  7. 算法题丨Remove Element

    描述 Given an array and a value, remove all instances of that value in-place and return the new length ...

  8. emqtt 试用(六)系统主题

    $SYS-系统主题 EMQ 消息服务器周期性发布自身运行状态.MQTT 协议统计.客户端上下线状态到 $SYS/ 开头系统主题. $SYS 主题路径以 "$SYS/brokers/{node ...

  9. 新概念英语(1-29)Come in, Amy.

    How must Amy clean the floor? A:Come in, Amy. Shut the door, please. This bedroom's very untidy. B:W ...

  10. io流的关闭顺序

    1.一般先打开的后关闭,后打开的先关闭 2.可以只关闭处理流,因为io流使用了装饰模式,所以关闭处理流时,会调用节点流的close()方法.