Description

题库链接

给你 \(n\) 个区间,让你选出其中一些分为两组,要求两组区间不能有交集,组内可以有交集。让你最大化两组之间区间个数较小的那一组的选取区间个数。以及对于每个区间 \(i\),回答第 \(i\) 个区间必选(放在第一组或者第二组),两组个数的最小值的最大值。

\(1\leq n\leq 200\)

Solution

首先,可以知道每组一定是若干个连续的时间段组成的。那么我们可以按时间来 DP,先离散化,设时间上限为 \(T\)。

为了方便转移,我们记 \(cnt_{i,j}\) 为全在 \([i,j]\) 时间段内的区间个数。这个是可以在 \(O(n^3)\) 内预处理出来的。

记 \(f_{i,j}\) 表示 \(1\sim i\) 时间段,第一组有 \(j\) 个区间时第二组最多有多少个区间。首先,若 \(i\) 这个时刻不选,可以继承 \(i-1\) 时刻的状态,那么赋值 \(f_{i,j}=f_{i-1},j\)。

考虑转移就是枚举以 \(i\) 为右端点,\(k\) 为左端点,这一整个时间段放在第一组或是第二组,显然对于每个 \(k\),\(f_{i,j}=\max\{f_{k-1,j}+cnt_{k,i},f_{k-1,j-cnt_{k,i}}\}\)。

那么第一问的答案显然就是 \(\max\limits_{0\leq i\leq n}\min\{i,f_{T,i}\}\)。

考虑第二问,首先我们仿照 \(f\) 的定义用相同的方式 DP 出一个数组 \(g\),表示 \(i\sim T\) 时间段,第一组有 \(j\) 个区间时第二组最多有多少个区间。

那么对于第 \(i\) 个区间,因为它必须被选,那么去考虑选择哪些时间段是包含第 \(i\) 个区间的。用 \(O(n^2)\) 去枚举端点 \([l,r]\),另外考虑 \(1\sim l-1\) 中放 \(a\) 个在第一组,\(r+1\sim T\) 中放 \(b\) 个在第一组。考虑 \([l,r]\) 放在第一组还是第二组,显然答案就是 \(\max\limits_{l,r,a,b}\{\min\{f_{l-1,a}+g_{r+1,b}+cnt_{l,r}, a+b\}, \min\{f_{l-1,a}+g_{r+1,b}, a+b+cnt_{l,r}\}\}\)。不过这样,单个询问就是 \(O(n^4)\) 的,吃不消。

容易发现上述计算时会有许多冗余重复的计算,那么我们考虑预处理一个数组 \(dp_{i,j}\) 表示 \([i,j]\) 区间必选,最大化最小区间个数的值。

显然对于每个 \(i,j\),我们只需枚举 \(1\sim i-1\) 中放在第一组个数 \(a\),\(j+1\sim T\) 中放在第一组个数 \(b\)。不过预处理这个数组还是 \(O(n^4)\) 的。

值得注意的是 \(f_{i,j}\) 随 \(j\) 增大,\(f\) 值单调不增。利用这个单调性,可以双指针优化,枚举 \(a\) 时,继承 \(b\) 值。最终复杂度为 \(O(n^3)\)。

预处理完,之后只需 \(O(n^2)\) 枚举端点就可以计算答案了。

综上复杂度为 \(O(n^3)\)。

Code

#include <bits/stdc++.h>
#define inf (-f[N-1][N-1])
using namespace std;
const int N = 405; int n, l, r, f[N][N], b[N], tot, cnt[N][N], g[N][N], dp[N][N];
struct tt {
int l, r;
} a[N]; int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d%d", &l, &r),
b[++tot] = a[i].l = l, b[++tot] = a[i].r = l+r-1;
sort(b+1, b+tot+1);
tot = unique(b+1, b+tot+1)-b-1;
for (int i = 1; i <= n; i++)
a[i].l = lower_bound(b+1, b+tot, a[i].l)-b,
a[i].r = lower_bound(b+1, b+tot, a[i].r)-b;
for (int i = 1; i <= tot; i++)
for (int j = i; j <= tot; j++)
for (int k = 1; k <= n; k++)
cnt[i][j] += (i <= a[k].l && a[k].r <= j);
memset(f, 192, sizeof(f));
memset(g, 192, sizeof(g));
f[0][0] = 0;
for (int i = 1; i <= tot; i++)
for (int j = 0; j <= n; j++) {
f[i][j] = f[i-1][j];
for (int k = i; k >= 1; k--) {
f[i][j] = max(f[i][j], f[k-1][j]+cnt[k][i]);
if (j >= cnt[k][i]) f[i][j] = max(f[i][j], f[k-1][j-cnt[k][i]]);
}
}
g[tot+1][0] = 0;
for (int i = tot; i >= 1; i--)
for (int j = 0; j <= n; j++) {
g[i][j] = g[i+1][j];
for (int k = i; k <= tot; k++) {
g[i][j] = max(g[i][j], g[k+1][j]+cnt[i][k]);
if (j >= cnt[i][k]) g[i][j] = max(g[i][j], g[k+1][j-cnt[i][k]]);
}
}
int ans = -inf;
for (int j = 0; j <= n; j++)
ans = max(ans, min(j, f[tot][j]));
printf("%d\n", ans);
for (int i = 1; i <= tot; i++)
for (int j = i; j <= tot; j++) {
int l = cnt[1][i-1];
for (int r = 0; r <= cnt[j+1][tot]; r++) {
while (l && max(min(f[i-1][l]+g[j+1][r]+cnt[i][j], l+r), min(f[i-1][l]+g[j+1][r], l+r+cnt[i][j]))
<= max(min(f[i-1][l-1]+g[j+1][r]+cnt[i][j], l-1+r), min(f[i-1][l-1]+g[j+1][r], l-1+r+cnt[i][j]))) --l;
dp[i][j] = max(dp[i][j], max(min(f[i-1][l]+g[j+1][r]+cnt[i][j], l+r), min(f[i-1][l]+g[j+1][r], l+r+cnt[i][j])));
}
}
for (int i = 1; i <= n; i++) {
int ans = 0;
for (int l = 1; l <= a[i].l; l++)
for (int r = a[i].r; r <= tot; r++)
ans = max(ans, dp[l][r]);
printf("%d\n", ans);
}
return 0;
}

[NOI 2011]NOI 嘉年华的更多相关文章

  1. P1308-道路修建 (noi 2011)

    题目描述 在 W 星球上有 n 个国家.为了各自国家的经济发展,他们决定在各个国家 之间建设双向道路使得国家之间连通.但是每个国家的国王都很吝啬,他们只愿 意修建恰好 n – 1 条双向道路. 每条道 ...

  2. NOI 2011 兔农 题解

    事先声明,本博客代码主要模仿accepoc,且仅针对一般如本博主一样的蒟蒻. 这道题不得不说数据良心,给了75分的水分,但剩下25分真心很难得到,因此我们就来讲一讲这剩下的25分. 首先,有数据可知他 ...

  3. noi 2011

    描述 已知长度最大为200位的正整数n,请求出2011^n的后四位. 输入 第一行为一个正整数k,代表有k组数据,k<=200接下来的k行, 每行都有一个正整数n,n的位数<=200 输出 ...

  4. 【BZOJ 2434】【NOI 2011】阿狸的打字机 fail树

    完全不会啊,看题解还看了好久,我是蒟蒻$QAQ$ $zyf$的题解挺好的:http://blog.csdn.net/clove_unique/article/details/51059425 $fai ...

  5. 博弈论(二分图匹配):NOI 2011 兔兔与蛋蛋游戏

    Description Input 输入的第一行包含两个正整数 n.m. 接下来 n行描述初始棋盘.其中第i 行包含 m个字符,每个字符都是大写英文字母"X".大写英文字母&quo ...

  6. [NOI 2011]阿狸的打字机

    Description 题库链接 给你 \(n\) 个单词, \(m\) 组询问,每组询问形同 \((x,y)\) ,询问 \(x\) 串在 \(y\) 串中出现多少次. \(1\leq n,m\le ...

  7. [NOI 2011]道路修建

    Description 在 W 星球上有 n 个国家.为了各自国家的经济发展,他们决定在各个国家 之间建设双向道路使得国家之间连通.但是每个国家的国王都很吝啬,他们只愿 意修建恰好 n – 1条双向道 ...

  8. NOI 2011 阿狸的打字机(AC自动机+主席树)

    题意 https://loj.ac/problem/2444 思路 ​多串匹配,考虑 \(\text{AC}\) 自动机.模拟打字的过程,先建出一棵 \(\text{Trie}\) 树,把它变成自动机 ...

  9. [NOI 2011][BZOJ 2434] 阿狸的打字机

    传送门 AC自动机 + 树状数组 建成AC自动机后,设end[i]为第i个串的末尾在Trie树上的节点. 可以发现,对于一个询问(x,y),ans等于Trie树上root到end[y]这条链上fail ...

随机推荐

  1. JS-禁用浏览器前进后退

    使用jQuery: <script type="text/javascript" language="javascript"> $(document ...

  2. 爬虫 - Scrapy中间件

    前提:看Scrapy架构图 不管什么Middlewares,都写在middlewares.py里面. 然后在settings.py里的DOWNLOADER_MIDDLEWARES或者SPIDER_MI ...

  3. 安卓基础(LiveData DataBinding)

    昨天因为有点事情,没有及时发表博客,昨天学习了LiveData和DataBinding,LiveData属于jetpack中的框架里面的,DataBinding可以进行数据绑定. 我分别利用这两部分知 ...

  4. [Python] Tkinter的食用方法_01_简单界面

    #开始 放假之后感觉整个人已经放飞自我了,完全不知道自己一天天在干什么,明明有很多的事情需要做,但是实际上每天啥都没做,,,虚度光阴... 晚上突然心烦意乱,开始思考今天一天都做了什么,感觉很有负罪感 ...

  5. 【题解】Rusty String [CF827E]

    [题解]Rusty String [CF827E] 传送门:\(\text{Rusty String}\) \(\text{[CF827E]}\) [题目描述] 多组数据,每组数据给出一个由 \(V, ...

  6. 吴裕雄 PYTHON 人工智能——基于MASK_RCNN目标检测(5)

    import os import sys import numpy as np import tensorflow as tf import matplotlib import matplotlib. ...

  7. Go语言基础之os

    文章引用自 package os import "os" os包提供了操作系统函数的不依赖平台的接口.设计为Unix风格的,虽然错误处理是go风格的:失败的调用会返回错误值而非错误 ...

  8. AcWing - 156 矩阵(二维哈希)

    题目链接:矩阵 题意:给定一个$m$行$n$列的$01$矩阵$($只包含数字$0$或$1$的矩阵$)$,再执行$q$次询问,每次询问给出一个$a$行$b$列的$01$矩阵,求该矩阵是否在原矩阵中出现过 ...

  9. VS中消除ANSI API警告

    最近在VS上写网络程序遇到许多问题,因为VS中将许多ANSI中的API都重写了,那些API大多有漏洞或不能支持现在的一些编程需求了,所以在VS中使用会因为警告而不能用. 但一些老API用着比较方便,了 ...

  10. 【Go语言系列】1.4、GO语言简介:第一个Go语言程序

    接下来我们来编写第一个 Go 程序 hello.go(Go 语言源文件的扩展是 .go),代码如下: // 声明 main 包 package main import ( "fmt" ...