[题面](https://www.luogu.org/problemnew/show/P4093)

好久没写博客了..最近新学了CDQ...于是就来发一发一道CDQ的练习题

看上去就是可以dp的样子。

设\(dp_{i}\)为以i结尾的最长不下降序列。

易得:\(dp_{i}\)=\(max(dp_{j})+1\)\((j<=i\)&&\(Max_{j}<=a_{i}\)&&\(a_{j}<=Min_{i})\)

\(Max_{i}\)和\(Min_{i}\)表示第i个点所有变化中的最大值和最小值。

我们考虑用一个什么东西来维护这个dp。

我的第一反应是树状数组套动态开点线段树,而且写那玩意应该也不会太长。

突然想到最近学了CDQ。

于是讲下CDQ怎么搞。

因为有两个两边不是同一个数组的条件,所以我们在solve的时候,要对\([l,mid]\)和\([mid+1,r]\)的根据不同的两个数组sort下,然后用个树状数组维护前缀max,算下左边对右边的贡献。

然后因为是dp,所以我们不能直接分治\([l,mid]\)和\([mid+1,r]\)然后合并,我们应该先分治\([l,mid]\)然后算好\([l,mid]\)对\([mid+1,r]\)的贡献,然后再去分治\([mid+1,r]\) (记得去做\([mid+1,r]\)前先把数组\([mid+1,r]\)恢复)

#include<cstdio>
#include<algorithm>
#include<string>
#define ll long long
#define For(i,x,y) for (register int i=(x);i<=(y);i++)
#define Dow(i,x,y) for (register int i=(x);i>=(y);i--)
#define cross(i,k) for (register int i=first[k];i;i=last[i]) using namespace std; inline ll read(){
ll x=0;int ch=getchar(),f=1;
while (!isdigit(ch)&&(ch!='-')&&(ch!=EOF)) ch=getchar();
if (ch=='-'){f=-1;ch=getchar();}
while (isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
} inline ll min(ll a,ll b){return a<b?a:b;}
inline ll max(ll a,ll b){return a>b?a:b;} const int N = 100010;
struct node{
int max,min,v,ans,id;
}a[N];
int n,m,x,y,ans,Max; int c[N];
inline void Add(int x,int y){for (;x<=Max;x+=x&(-x)) c[x]=max(c[x],y);}
inline int Query(int x){int ans=0;for (;x;x-=x&(-x)) ans=max(ans,c[x]);return ans;}
inline void Clear(int x){for (;x<=Max;x+=x&(-x)) c[x]=0;} inline bool cmp1(node a,node b){return a.max<b.max;}
inline bool cmp2(node a,node b){return a.v<b.v;}
inline bool cmp3(node a,node b){return a.id<b.id;}
inline void CDQ(int l,int r){
if (l==r) return;
int mid=l+r>>1;
CDQ(l,mid);
sort(a+l,a+mid+1,cmp1),sort(a+mid+1,a+r+1,cmp2);
int L=l,R=mid+1;
for (;L<=mid&&R<=r;R++){
for (;a[L].max<=a[R].v&&L<=mid;L++) Add(a[L].v,a[L].ans);
a[R].ans=max(a[R].ans,Query(a[R].min)+1);
}
For(i,R,r) a[i].ans=max(a[i].ans,Query(a[i].min)+1);
For(i,l,L) Clear(a[i].v);
sort(a+mid+1,a+r+1,cmp3);
CDQ(mid+1,r);
} int main(){
n=read(),m=read();
For(i,1,n) a[i].v=a[i].max=a[i].min=read(),a[i].id=i;
For(i,1,m){
x=read(),y=read();
a[x].max=max(a[x].max,y),a[x].min=min(a[x].min,y);
}
For(i,1,n) Max=max(Max,max(a[i].v,a[i].min)),a[i].ans=1;
//For(i,1,n) printf("%d %d %d\n",a[i].v,a[i].min,a[i].max);puts("");
CDQ(1,n);
For(i,1,n) ans=max(ans,a[i].ans);
//For(i,1,n) printf("%d %d %d %d\n",a[i].v,a[i].min,a[i].max,a[i].ans);
printf("%d",ans);
}

Luogu P4093 [HEOI2016/TJOI2016]序列 dp套CDQ的更多相关文章

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

    洛谷 P4093 [HEOI2016/TJOI2016]序列 CDQ分治优化DP 题目描述 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他. 玩具上有一个数列,数列中某些项的值可能会 ...

  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. BZOJ.4553.[HEOI2016&TJOI2016]序列(DP 树状数组套线段树/二维线段树(MLE) 动态开点)

    题目链接:BZOJ 洛谷 \(O(n^2)\)DP很好写,对于当前的i从之前满足条件的j中选一个最大值,\(dp[i]=d[j]+1\) for(int j=1; j<i; ++j) if(a[ ...

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

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

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

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

  7. P4093 [HEOI2016/TJOI2016]序列

    题目链接 题意分析 我们假设每一个数都有一个变动范围\([L_i,R_i]\) 那么我们令\(dp[i]\)表示以\(i\)结尾的最长不下降子序列的长度 那么就是\(dp[i]=max\{dp[j]+ ...

  8. cdq分治(hdu 5618 Jam's problem again[陌上花开]、CQOI 2011 动态逆序对、hdu 4742 Pinball Game、hdu 4456 Crowd、[HEOI2016/TJOI2016]序列、[NOI2007]货币兑换 )

    hdu 5618 Jam's problem again #include <bits/stdc++.h> #define MAXN 100010 using namespace std; ...

  9. [Luogu P2824] [HEOI2016/TJOI2016]排序 (线段树+二分答案)

    题面 传送门:https://www.luogu.org/problemnew/show/P2824 Solution 这题极其巧妙. 首先,如果直接做m次排序,显然会T得起飞. 注意一点:我们只需要 ...

随机推荐

  1. 基于 Docker 的 Zabbix 微服务系统

    zabbix 官网提供一个镜像 [ zabbix-appliance ], 可以直接拉起一个 zabbix-server. 但是数据库无法分离出来. 本实践使用 zabbix 官方提供的 Docker ...

  2. bzoj 1483 链表启发式合并

    首先我们可以比较容易的在n的时间内算出来开始的答案,我们维护一些链表,分别表示不同的颜色,那么我们在计算答案的时候,只需要扫一遍所有的链表,判断链表相邻两项是否在序列中相邻,不相邻的话肯定在这其中的一 ...

  3. linux进程管理-定时定期执行任务

     0.计划任务的命令: at 安排作业在某一时刻执行 batch 安排作业在系统负载不重时执行 crontab 安排周期性运行的作业 1.at命令用法: 安排命令或者多个命令在指定的时间运行一次 语法 ...

  4. Linux 入门记录:十五、Linux 网络基本配置

    一.以太网(Ethernet) 以太网(Ethernet)是一种计算机局域网技术.IEEE 组织的 IEEE 802.3 标准制定了以太网的技术标准,它规定了包括物理层的连线.电子信号和介质访问层协议 ...

  5. JSON对象与字符串之间的相互转换

    <html> <head> <meta name="viewport" content="width=device-width" ...

  6. HDU 6188 Duizi and Shunzi 贪心

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6188 题意:给了n个数,然后现在问我们最多构成多少个对子和顺子,其中对子是2个相同的牌,顺子是3个连续 ...

  7. JDBC数据源连接池(1)---DBCP

    何为数据源呢?也就是数据的来源.我在前面的一篇文章<JDBC原生数据库连接>中,采用了mysql数据库,数据来源于mysql,那么mysql就是一种数据源.在实际工作中,除了mysql,往 ...

  8. cf786a

    title: CodeForces 786A Berzerk data: 2018-3-3 10:29:40 tags: 博弈论 bfs 无限 with draw copyright: true ca ...

  9. 【DUBBO】dubbo的Router接口

    Router服务路由, 根据路由规则从多个Invoker中选出一个子集AbstractDirectory是所有目录服务实现的上层抽象, 它在list列举出所有invokers后,会在通过Router服 ...

  10. C语言实现二叉排序树

    程序以'#'结尾的二叉排序树. /*(双重指针 BSTree *T)问:数据结构中 二叉树建立结点为什么用 双重指针?详细解释下双重指针 答:指针的指针.因为树的结点要用指针描述.如果只用指针,作形参 ...