洛谷 P4093 [HEOI2016/TJOI2016]序列 CDQ分治优化DP

题目描述

佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他。

玩具上有一个数列,数列中某些项的值可能会变化,但同一个时刻最多只有一个值发生变化。现在佳媛姐姐已经研究出了所有变化的可能性,她想请教你,能否选出一个子序列,使得在任意一种变化中,这个子序列都是不降的?请你告诉她这个子序列的最长长度即可。

输入格式

输入的第一行有两个正整数 \(n,m\),分别表示序列的长度和变化的个数。

接下来一行有 \(n\) 个整数,表示这个数列原始的状态。

接下来 \(m\) 行,每行有 \(2\) 个整数 \(x,y\),表示数列的第 \(x\) 项可以变化成 \(y\) 这个值。

输出格式

输出一个整数,表示对应的答案。

输入输出样例

输入 #1

3 4

1 2 3

1 2

2 3

2 1

3 4

输出 #1

3

说明/提示

注意:每种变化最多只有一个值发生变化。

在样例输入中,所有的变化是:

1 2 3

2 2 3

1 3 3

1 1 3

1 2 4

选择子序列为原序列,即在任意一种变化中均为不降子序列。

对于 \(20\%\) 数据,所有数均为正整数,且小于等于 \(300\)。

对于 \(50\%\) 数据,所有数字均为正整数,且小于等于 \(3000\)。

对于 \(100\%\) 数据,所有数字均为正整数,且小于等于 \(10^5\)。\(1\le x\le n\)。

分析

我们设\(min[i]\)为处在位置\(i\)上的数变化得到的最小值,\(max[i]\)为处在位置\(i\)上的数变化得到的最大值,\(f[i]\)为以\(i\)结尾的最长上升子序列的长度

则\(f[i]=max(f[i],f[j]+1),j<i,max[j] \leq i,min[i] \geq j\)\

我们会发现这是一个三位偏序问题,可以用\(CDQ\)分治优化

代码

#include<cstdio>
#include<algorithm>
#include<iostream>
inline int read(){
int x=0,fh=1;
char ch=getchar();
while(ch<'0' || ch>'9'){
if(ch=='-') fh=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*fh;
}
const int maxn=1e6+5;
int f[maxn],a[maxn],mmax[maxn],mmin[maxn],tr[maxn],n,m;
int lb(int xx){
return xx&-xx;
}
void ad(int wz,int val){
for(int i=wz;i<maxn;i+=lb(i)){
tr[i]=std::max(tr[i],val);
}
}
int cx(int wz){
int ans=0;
for(int i=wz;i>0;i-=lb(i)){
ans=std::max(tr[i],ans);
}
return ans;
}
void qk(int wz){
for(int i=wz;i<maxn;i+=lb(i)){
tr[i]=0;
}
}
int tot=1,id[maxn];
bool cmp1(int aa,int bb){
return a[aa]<a[bb];
}
bool cmp2(int aa,int bb){
return mmin[aa]<mmin[bb];
}
void solve(int l,int r){
if(l==r) return;
int mids=(l+r)>>1;
solve(l,mids);
for(int i=l;i<=r;i++) id[i]=i;
std::sort(id+l,id+mids+1,cmp1);
std::sort(id+mids+1,id+r+1,cmp2);
int now=l;
for(int i=mids+1;i<=r;i++){
while(a[id[now]]<=mmin[id[i]] && now<=mids){
ad(mmax[id[now]],f[id[now]]);
now++;
}
f[id[i]]=std::max(f[id[i]],cx(a[id[i]])+1);
tot=std::max(tot,f[id[i]]);
}
for(int i=now-1;i>=l;i--){
qk(mmax[id[i]]);
}
solve(mids+1,r);
}
int main(){
n=read(),m=read();
for(int i=1;i<=n;i++){
a[i]=read();
mmax[i]=mmin[i]=a[i];
f[i]=1;
}
for(int i=1;i<=m;i++){
int aa,bb;
aa=read(),bb=read();
mmax[aa]=std::max(mmax[aa],bb);
mmin[aa]=std::min(mmin[aa],bb);
}
solve(1,n);
printf("%d\n",tot);
return 0;
}

洛谷 P4093 [HEOI2016/TJOI2016]序列 CDQ分治优化DP的更多相关文章

  1. BZOJ4553/洛谷P4093 [HEOI2016/TJOI2016]序列 动态规划 分治

    原文链接http://www.cnblogs.com/zhouzhendong/p/8672434.html 题目传送门 - BZOJ4553 题目传送门 - 洛谷P4093 题解 设$Li$表示第$ ...

  2. 洛谷 P4093 [HEOI2016/TJOI2016]序列 解题报告

    P4093 [HEOI2016/TJOI2016]序列 题目描述 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他.玩具上有一个数列,数列中某些项的值可能会变化,但同一个时刻最多只有一 ...

  3. 洛谷 P4093 [HEOI2016/TJOI2016]序列(Cdq+dp)

    题面 luogu 题解 \(Cdq分治+dp\) \(mx[i],mn[i]\)分别表示第\(i\)位最大,最小能取到多少 那么有 \(j < i\) \(mx[j] \le a[i]\) \( ...

  4. 洛谷P4093 [HEOI2016/TJOI2016]序列

    题目描述 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他.玩具上有一个数列,数列中某些项的值可能会变化,但同一个时刻最多只有一个值发生变化.现在佳媛姐姐已经研究出了所有变化的可能性, ...

  5. 【洛谷P4093】 [HEOI2016/TJOI2016]序列 CDQ分治+动态规划

    你发现只会改变一个位置,所以可以直接进行dp 具体转移的话用 CDQ 分治转移就好了~ #include <bits/stdc++.h> #define N 100006 #define ...

  6. 洛谷 P5331 - [SNOI2019]通信(CDQ 分治优化建图+费用流)

    题面传送门 首先熟悉网络流的同学应该能一眼看出此题的建模方法: 将每个点拆成两个点 \(in_i,out_i\),连一条 \(S\to in_i\),容量为 \(1\) 费用为 \(0\) 的边 连一 ...

  7. [HEOI2016/TJOI2016]序列 CDQ分治

    ---题面--- 题解: 首先我们观察一下,如果一个点对(j, i), 要符合题中要求要满足哪些条件? 首先我们设 j < i 那么有: j < i max[j] < v[i] v[ ...

  8. luogu4093 序列 (cdq分治优化dp)

    设f[i]是以i位置为结尾的最长满足条件子序列的长度 那么j能转移到i的条件是,$j<i , max[j]<=a[i] , a[j]<=min[i]$,其中max和min表示这个位置 ...

  9. 洛谷 P3580 - [POI2014]ZAL-Freight(单调队列优化 dp)

    洛谷题面传送门 考虑一个平凡的 DP:我们设 \(dp_i\) 表示前 \(i\) 辆车一来一回所需的最小时间. 注意到我们每次肯定会让某一段连续的火车一趟过去又一趟回来,故转移可以枚举上一段结束位置 ...

随机推荐

  1. JVM与Java体系结构

    参考笔记:https://blog.csdn.net/weixin_45759791/article/details/107322503 前言 作为Java工程师的你曾被伤害过吗?你是否也遇到过这些问 ...

  2. 【av68676164(p54)】段式和段页式虚拟存储

    段式存储管理 进程分段 把进程按逻辑意义划分为多个段,每段有段名,长度不定,进程由多段组成 例:一个具有代码段.数据段和堆栈段的进程 段式内存管理系统的内存分配 以段为的单位装入,每段分配连续的内存 ...

  3. PHP基础之查找

    前言 之前的文章介绍了PHP的运算符.流程控制.函数.排序等.有兴趣可以去看看. PHP入门之类型与运算符 PHP入门之流程控制 PHP入门之函数 PHP入门之数组 PHP基础之排序 下面简单介绍一下 ...

  4. XSS 渗透思路笔记

    了解XSS首先要了解HTML里面的元素:共有5种元素:空元素.原始文本元素. RCDATA元素.外来元素以及常规元素. 空元素area.base.br.col. command. embed.hr.i ...

  5. MySQL 连接查询汇总

    MYSQL-连接查询: # 连接查询:把多张表进行记录的连接(按照某个条件进行数据的拼接) # 分类 1,内链接 2,外连接 # 左外 # 右外 3,自然连接 4,交叉连接 MYSQL-内链接 : # ...

  6. C#LeetCode刷题之#40-组合总和 II(Combination Sum II)

    目录 问题 示例 分析 问题 该文章已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3666 访问. 给定一个数组 candidates ...

  7. 线段树(二)STEP

    线段树(二) 线段树例题整理 Part 1:题面 传送门:https://www.luogu.com.cn/problem/P6492(靠之前传送门放错了,暴露了我在机房逛B站的事实-- Part 2 ...

  8. 初识ABP vNext(3):vue对接ABP基本思路

    目录 前言 开始 登录 权限 本地化 创建项目 ABP vue-element-admin 最后 前言 上一篇介绍了ABP的启动模板以及AbpHelper工具的基本使用,这一篇将进入项目实战部分.因为 ...

  9. Android 在代码中修改TextView的DrawableRight等方向上的图片

    在XML文件中可以对TextView进行设置: android:drawableTop="@drawable/XXX" android:drawableBottom="@ ...

  10. Linux C++实现一服务器与多客户端之间的通信

    通过网络查找资料得到的都是一些零碎不成体系的知识点,无法融会贯通.而且需要筛选有用的信息,这需要花费大量的时间.所以把写代码过程中用到的相关知识的博客链接附在用到的位置,方便回顾. 1.程序流程 服务 ...