首页 > [NOI2011]Noi嘉年华

[NOI2011]Noi嘉年华

题解:

我们设计状态方程如下:

num[i][j]表示从时间i到j中有多少个

pre[i][j]表示时间1~i中,A选了j个时的B能选的数量的最大值.

nex[i][j]表示时间i~cnt中,A选了j个时的B能选的数量的最大值.

mus[i][j]表示从时间i到j的保证选时,A和B选的数量中的较小值的最大值.

①对于num数组直接可以暴力求,没问题.

②对于pre和nex数组在这里就只讲pre的转移,nex的转移类似.

pre[i][j]=max(pre[i-1][j],pre[k][j]+num[k][i],pre[k][j-num[k][i]]);(1<=k
就是分成不管i时间,或者从时间k到i的都由B选,或者从时间k到i的都由A选三种情况

③对于mus数组,我们得到转移方程mus[i][j]=max(min(x+y,pre[i][x]+num[i][j]+nex[j][y])),x表示时间1~i中A选x个,y表示时间j~cnt中A选y个,中间num[i][j]个由B选.这样暴力转移的话是O(n^4)的,时间上是不允许的,那么我们观察转移方程,当x增大时,y只有单调递减答案才会更优,因为如果x增大且y也增大的话,表示A选的越来越多,B选的越来越少,显然答案不会更优的,所以我们维护一个y的单调递减的指针来转移就可以了,时间O(n^3).

④对于第一问的答案就是max(min(pre[i][j],j)),枚举时间i和A选的个数j来得到最优解.

然后对于第二问我们对于一个活动l~r,答案为max(mus[i][j]),1<=i<=l,r<=j<=cnt.

#include
#include
#include
#include
#include
#include
#include
#include
#include
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define MAXN 10100
#define RG register
#define LL long long int
using namespace std;
const int INF=1e9;
struct node{int l,r;int id;
}t[1010];
int n;
int num[1010][1010];//从时间i到j中有多少个
int pre[1010][1010];//时间1~i中,A选了j个时的B能选的数量的最大值.
int nex[1010][1010];//时间i~n中,A选了j个时的B能选的数量的最大值.
int mus[1010][1010];//从时间i到j的保证选时,A和B选的数量中的较小值的最大值.
int st[MAXN],cnt;
int ans[MAXN];
int main()
{freopen("1.in","r",stdin);scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d%d",&t[i].l,&t[i].r);t[i].r+=t[i].l;t[i].id=i;st[++cnt]=t[i].l;st[++cnt]=t[i].r;}sort(st+1,st+cnt+1);cnt=unique(st+1,st+cnt+1)-st-1;for(int i=1;i<=n;i++){t[i].l=lower_bound(st+1,st+cnt+1,t[i].l)-st;t[i].r=lower_bound(st+1,st+cnt+1,t[i].r)-st;}for(int i=1;i<=cnt;i++)for(int j=1;j<=t[i].l;j++)for(int k=t[i].r;k<=cnt;k++)num[j][k]++;for(int i=1;i<=cnt;i++)for(int j=1;j<=n;j++)pre[i][j]=nex[i][j]=-INF;pre[0][0]=nex[cnt+1][0]=0;for(int i=1;i<=cnt;i++){for(int j=0;j<=num[1][i];j++)pre[i][j]=max(pre[i-1][j],pre[i][j]);for(int j=0;j<=num[1][i];j++){for(int k=1;k=num[k][i]) pre[i][j]=max(pre[k][j-num[k][i]],pre[i][j]);}}}for(int i=cnt;i>=1;i--){for(int j=0;j<=num[i][cnt];j++)nex[i][j]=max(nex[i+1][j],nex[i][j]);for(int j=0;j<=num[i][cnt];j++){for(int k=cnt;k>i;k--){nex[i][j]=max(nex[k][j]+num[i][k],nex[i][j]);if(j>=num[i][k]) nex[i][j]=max(nex[k][j-num[i][k]],nex[i][j]);}}}for(int i=1;i<=cnt;i++)for(int j=i+1;j<=cnt;j++){for(int x=0,y=n;x<=n;x++){while(y){int val1=min(x+y,pre[i][x]+num[i][j]+nex[j][y]);int val2=min(x+y-1,pre[i][x]+num[i][j]+nex[j][y-1]);if(val2>=val1) y--;else break;}mus[i][j]=max(mus[i][j],min(x+y,pre[i][x]+num[i][j]+nex[j][y]));}}for(int i=1;i<=cnt;i++)for(int j=0;j<=num[1][i];j++)ans[0]=max(ans[0],min(pre[i][j],j));for(int i=1;i<=n;i++)for(int j=t[i].l;j>=1;j--)for(int k=t[i].r;k<=cnt;k++)ans[i]=max(ans[i],mus[j][k]);for(int i=0;i<=n;i++) printf("%d
",ans[i]);return 0;
}

 

转载于:https://www.cnblogs.com/Landlord-greatly/p/8144349.html

更多相关:

  •         Apache POI是一个开源的利用Java读写Excel,WORD等微软OLE2组件文档的项目。        我的需求是对Excel的数据进行导入或将数据以Excel的形式导出。先上简单的测试代码:package com.xing.studyTest.poi;import java.io.FileInputSt...

  • 要取得[a,b)的随机整数,使用(rand() % (b-a))+ a; 要取得[a,b]的随机整数,使用(rand() % (b-a+1))+ a; 要取得(a,b]的随机整数,使用(rand() % (b-a))+ a + 1; 通用公式:a + rand() % n;其中的a是起始值,n是整数的范围。 要取得a到b之间的...

  • 利用本征图像分解(Intrinsic Image Decomposition)算法,将图像分解为shading(illumination) image 和 reflectance(albedo) image,计算图像的reflectance image。 Reflectance Image 是指在变化的光照条件下能够维持不变的图像部分...

  • 题目:面试题39. 数组中出现次数超过一半的数字 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。 你可以假设数组是非空的,并且给定的数组总是存在多数元素。 示例 1: 输入: [1, 2, 3, 2, 2, 2, 5, 4, 2] 输出: 2 限制: 1 <= 数组长度 <= 50000 解题: cl...

  • 题目:二叉搜索树的后序遍历序列 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。 参考以下这颗二叉搜索树:      5     /    2   6   /  1   3示例 1: 输入: [1,6,3,2,5] 输出...

  • 用python编写乘法口诀表的方法 发布时间:2020-08-25 11:46:35 来源:亿速云 阅读:60 作者:小新 用python编写乘法口诀表的方法?这个问题可能是我们日常学习或工作经常见到的。希望通过这个问题能让你收获颇深。下面是小编给大家带来的参考内容,让我们一起来看看吧! 第一种:使用for遍历循环嵌套for x in...

  • //很长一段时间我都只使用以下方式做数组循环,具体原因看数据 var aa = for (var i = 0, l = aa.length; i < l; i++) { var a = aa[i];} 数据采集图片来源于网友 很明显,for循环第二种方式完胜!!! 至于for in、forEach什么的,不知道甩他们多少...

  • 目录 1. Scene Graph Generation with External Knowledge and Image Reconstruction 2. Knowledge Acquisition for Visual Question Answering via Iterative Querying Author...

  • 基础题1: 输入一个正整数 n (1≤n≤10)和n 阶方阵a的元素,如果方阵a中的所有元素都沿主对角线对称,输出“Yes”, 否则,输出“No”。主对角线为从矩阵的左上角至右下角的连线,方阵a中的所有元素都沿主对角线对称指对所有i, k,a[i][k]和a[k][i]相等。输入输出示例如下: 输入: 3 1 2 3 4 5 6 7...

  • 程序流程控制 分支 顺序 循环 if switch&case 1 2 3 调整 break 1.6 前 switch(byte、short、char、int) 1.7 可放String 循环 while(次数不确定) do while for(确定次数) break(跳出本层循环) continue(跳出本次循环)     *   2...