[题面](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. python学习笔记(五)数值类型和类型转换

    Python中的数值类型有: 整型,如2,520 浮点型,如3.14159,1.5e10 布尔类型 True和False e记法: e记法即对应数学中的科学记数法 >>> 1.5e1 ...

  2. sqlserver 树形结构表查询 获取拼接结果

    树形表结构如下 IF EXISTS (SELECT * FROM sys.all_objects WHERE object_id = OBJECT_ID(N'[dbo].[Test]') AND ty ...

  3. Vue组件-使用插槽分发内容

    在使用组件时,我们常常要像这样组合它们: <app> <app-header></app-header> <app-footer></app-fo ...

  4. DIV+CSS综合实例【传智PHP首页】

    1.首页结构 2.准备工作 所有素材放到与当前网页同级的目录下: 网页背景色.背景图: 主页宽度:1000px: 创建CSS文件,将CSS文件引入到当前的HTML文件中. 3.实现 效果图: HTML ...

  5. python实战===itchat

    import itchat itchat.login() friends=itchat.get_friends(update=True)[0:] male=female=other=0 for i i ...

  6. qt-creator

    https://github.com/qt-creator/qt-creator https://github.com/qt-creator

  7. Queue类

    1.LinkedBlockingQueue:基于链接节点的可选限定的blocking queue . 这个队列排列元素FIFO(先进先出). 队列的头部是队列中最长的元素. 队列的尾部是队列中最短时间 ...

  8. 003 CopyOnWriteArrayList原理

    聊聊并发-Java中的Copy-On-Write容器 Copy-On-Write简称COW,是一种用于程序设计中的优化策略.其基本思路是,从一开始大家都在共享同一个内容,当某个人想要修改这个内容的时候 ...

  9. 2.ubuntu的使用

    1. CTRL+ALT+T 可以将命令模式打开 2. 有可能没办法进行yum ,它会告诉你操作的方法 3. 有些操作需要获得root的权限才可以,我们得进入root状态 --> sudo pas ...

  10. google fcm 推送的流程

    总结:1.给一个人推,能成功,2.给多个人推,有两种,一种是给组推,一种是给主题推,之前用的是组推,但是不成功,这里换成主题推: <?phpnamespace App\Http\Controll ...