【eJOI2020】考试(dp & 树状数组优化)
Description
\(n\) 个正整数排成一列,每个位置 \(i\) 有一个初始值 \(A_i\) 以及目标值 \(B_i\)。
一次操作可以选定一个区间 \([l, r]\),并将区间内所有数赋值为 \(\max_{i\in[l, r]} A_i\)。
你可以进行任意次操作,每次操作基于上次操作的结果。
求结果若干次操作后,使得与操作后的值与目标值相同的位置数最大化。
Hint
\(1\le n\le 10^5, 1\le A_i, B_i\le 10^9\)。
原题数据过于奇妙于是就直接取最大值反正能做。官方那个三合一做法真的 /no
Solution
首先,我们不难求出对于每个 \(i\in[1, n]\),该位置可以向左侧取到目标值 \(B_i = A_j\) 的第一个位置 \(L_i = j(\le i)\) 或者不存在,同理对于右侧 \(R_i\) 我们也这么干。
为什么我们只取第一个位置呢?显然可能存在多个可取的位置,不过注意到我们对位置 \(i\) 向 \(j\) 进行一次取值操作之后,会对中间的这些值造成影响。我们希望成功的取值操作尽可能多,那么影响的范围自然是越少越好了。
观察到一个性质,对于一个 \(i\),如果 \(L_i\) (\(R_i\) 同理不再赘述)存在,说明 \(j\in[L_i +1, i]\) 这个区间的所有 \(A_j\) 的值都小于 \(A_{L_i}\)。那么一次操作下去,所有这个区间内的值都会失效,如果有像“从 \(A_j\) 取值到 \(k(<i)\)”这样的操作那必然不能同时与当前这个同时执行。
于是我们尝试大力将题目转化:有两排点,每排 \(n\) 个,对于第一排每个点 \(i\) 向第二排的第 \(L_i, R_i\) 个点分别连一条边。若选取一个第一排的点 \(i\),那么需要至少选中连接 \(i\) 的两条或一条边的一条边(没有边则不能选)。要求选中的边两两不相交(除端点外),求最多选取第三个第一排的点。
发现当 \(A_i\) 互不相同时,每个点最多连出去 \(1\) 条边,这就是个经典的 LIS 问题,不过稍加拓展就可以得到本题的正解。
还是令 \(f(i, j)\) 为处理到第一排前 \(i\) 个点,第二排涉及到的点编号最大的为 \(j\),可以选出第一排点个数的最大值。那么转移比较简单:
\]
不难发现把 \(i\) 滚掉之后实质上就是一个前缀 \(\max\),于是使用树状数组优化为 \(O(n\log n)\)。
Code
/*
* Author : _Wallace_
* Source : https://www.cnblogs.com/-Wallace-/
* Problem : eJOI2020 Exam
*/
#include <algorithm>
#include <cstdio>
#include <set>
#include <vector>
using namespace std;
const int N = 1e5 + 5;
int n;
int A[N], B[N];
int L[N], R[N];
int tr[N]; // 树状数组求前缀 max
inline void upd(int p, int v) {
for (; p <= n; p += p & -p) tr[p] = max(tr[p], v);
}
inline int get(int p) {
int v = 0;
for (; p; p -= p & -p) v = max(tr[p], v);
return v;
}
signed main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", A + i);
for (int i = 1; i <= n; i++) scanf("%d", B + i);
vector<pair<int, int> > tmp(n * 2);
set<int> rec({0, n + 1});
for (int i = 1; i <= n; i++) tmp[i - 1] = {A[i], i};
for (int i = 1; i <= n; i++) tmp[i + n - 1] = {B[i], -i};
sort(tmp.begin(), tmp.end(), greater<pair<int, int> >());
for (auto it : tmp) {
if (it.second < 0) {
int l = *rec.lower_bound(-it.second);
if (A[l] == it.first) R[-it.second] = l;
int r = *--rec.upper_bound(-it.second);
if (A[r] == it.first) L[-it.second] = r;
} else rec.insert(it.second);
} // 求 L & R
for (int i = 1; i <= n; i++) { // 同步更新
int l = get(L[i]), r = get(R[i]);
if (L[i]) upd(L[i], l + 1);
if (R[i]) upd(R[i], r + 1);
}
printf("%d\n", get(n));
return 0;
}
【eJOI2020】考试(dp & 树状数组优化)的更多相关文章
- Codeforces 909 C. Python Indentation (DP+树状数组优化)
题目链接:Python Indentation 题意: Python是没有大括号来标明语句块的,而是用严格的缩进来体现.现在有一种简化版的Python,只有两种语句: (1)'s'语句:Simple ...
- 2015南阳CCPC C - The Battle of Chibi DP树状数组优化
C - The Battle of Chibi Description Cao Cao made up a big army and was going to invade the whole Sou ...
- bzoj 3594: [Scoi2014]方伯伯的玉米田 dp树状数组优化
3594: [Scoi2014]方伯伯的玉米田 Time Limit: 60 Sec Memory Limit: 128 MBSubmit: 314 Solved: 132[Submit][Sta ...
- FZU2236 第十四个目标 dp+树状数组优化
分析:这种题烂大街,n^2,然后数据结构优化下到nlogn,离散化 #include <cstdio> #include <cstring> #include <queu ...
- Codeforces 909C Python Indentation:树状数组优化dp
题目链接:http://codeforces.com/contest/909/problem/C 题意: Python是没有大括号来标明语句块的,而是用严格的缩进来体现. 现在有一种简化版的Pytho ...
- BZOJ3594: [Scoi2014]方伯伯的玉米田【二维树状数组优化DP】
Description 方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美. 这排玉米一共有N株,它们的高度参差不齐. 方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感 ...
- HDU 6240 Server(2017 CCPC哈尔滨站 K题,01分数规划 + 树状数组优化DP)
题目链接 2017 CCPC Harbin Problem K 题意 给定若干物品,每个物品可以覆盖一个区间.现在要覆盖区间$[1, t]$. 求选出来的物品的$\frac{∑a_{i}}{∑b_ ...
- Codeforces 946G Almost Increasing Array (树状数组优化DP)
题目链接 Educational Codeforces Round 39 Problem G 题意 给定一个序列,求把他变成Almost Increasing Array需要改变的最小元素个数. ...
- Codeforces 629D Babaei and Birthday Cake(树状数组优化dp)
题意: 线段树做法 分析: 因为每次都是在当前位置的前缀区间查询最大值,所以可以直接用树状数组优化.比线段树快了12ms~ 代码: #include<cstdio> #include< ...
随机推荐
- Python项目2:弹幕复读机
目录 一.功能 二.思路 三.实现 1. 获取弹幕 2. 发送弹幕 3. 封装调用 这个项目是我从B站的一个up主那学到的(原视频号269525280),感觉很是有趣,就是很欠打哈哈 一.功能 功能很 ...
- simple-rpc
RPC的实现原理 正如上一讲所说,RPC主要是为了解决的两个问题: 解决分布式系统中,服务之间的调用问题. 远程调用时,要能够像本地调用一样方便,让调用者感知不到远程调用的逻辑. 还是以计算器Calc ...
- Java初始化静态变量的时间顺序
1. 开始吧! 今天,我们来探讨交流下静态变量初始化过程.Java虚拟机在类加载期间也同样遵循这个过程. 2. 初始化过程 在较高的层次上,JVM执行以下步骤: 首先,加载并链接类.然后,这个过程的& ...
- 汇编语言常用的DOS功能调用
今天掌握了汇编语言常用的DOS功能调用,现在列出来供参考. 1.单字符输入(1号调用) 格式:MOV AH,1 INT 21H 功能:达到输入状态,从键盘上输入字符的ASCII码送入AX中,并送显示器 ...
- webpack : 无法加载文件 C:\Users\Eileen\AppData\Roaming\npm\webpack.ps1,因为在此系统上禁止运行脚本
报错内容: webpack : 无法加载文件 C:\Users\Eileen\AppData\Roaming\npm\webpack.ps1,因为在此系统上禁止运行脚本.有关详细信息,请参阅 http ...
- 学习Validator验证框架总结
在项目开发中许多地方需要加以验证,对于使用if-else简单粗暴一个一个验证,spring的validation封装了Javax ValidationI校验参数,大大缩减了代码量. 以前的分层验证,从 ...
- configure.ac和Makefile.am的格式解析概述
1. configure.ac和Makefile.am的格式解析概述 1.1. Autotools相关工具链 1.1.1. Autotools 1.1.2. 其他相关工具 1.2. 工具链的流程 1. ...
- .net core quartz job作业调度管理组件
定时作业对于多数系统来说,都会用到,定时作业的实现方式可以有多种方式,简单的方式用Timer就可以实现,但是达不到通用的效果,本文采用Quartz基础组件来搭建一套企业通用的作业调度管理服务,希望对于 ...
- 应聘阿里,字节跳动美团90%会问到的JVM面试题! 史上最全系列!
Java 内存分配 • 寄存器:程序计数器,是线程私有的,就是一个指针,指向方法区中的方法字节码.• 静态域:static 定义的静态成员.• 常量池:编译时被确定并保存在 .class 文件中的(f ...
- 使用Camtasia来给视频或者图片调色
喜欢摄影和制作视频的朋友可能知道,一张好看的照片或一段精美视频的构成要素很多,取景本身就是很重要的条件,相机的硬件水平也是一个重要因素,接下来的就是后期的编辑和处理了,而在后期处理过程中调色是十分重要 ...