题目链接:BZOJ 洛谷

\(O(n^2)\)DP很好写,对于当前的i从之前满足条件的j中选一个最大值,\(dp[i]=d[j]+1\)

 for(int j=1; j<i; ++j)
if(a[j]<=minv[i]&&maxv[j]<=a[i])//序列只会变换一次
dp[i]=max{dp[j]+1};

转移要满足两个条件:\(a[j]<=minv[i]\ \&\&\ maxv[j]<=a[i]\)

一个二维偏序问题,CDQ、树套树都可以。

拿\(minv[x]\)和\(a[y]\)作为两个坐标轴,\(dp[j]\)表示其上一点\((A[j],maxv[j])\).

这样就成了一个二维平面,可以向其中插入一些点dp[i],询问一个矩形区域(也是一段前缀)中某点最大值

线段树套线段树 树状数组套线段树都可做 复杂度\(O(nlog^2n)\)

后者时间还可以

树状数组套线段树:

//企图二维树状数组 但动态开点的话 中间一段没有的区间会中断y方向的Query..
#include<cstdio>
#include<cctype>
#include<algorithm>
#define gc() getchar()
#define now node[rt]
#define lson l,m,node[rt].ls
#define rson m+1,r,node[rt].rs
#define lb(x) ((x)&-(x))
const int N=1e5+5; int n,m,A[N],minv[N],maxv[N],MaxV,MaxA;
namespace Tree_2D
{
struct Seg_Tree
{
struct Node
{
int maxv,ls,rs;
}node[N<<6];//还要再小点。。不然BZOJ上依旧MLE
inline int new_Node()
{
static int cnt=0;
return ++cnt;
}
void Insert(int l,int r,int &rt,int p,int v)
{
if(!rt) rt = new_Node();
now.maxv = std::max(now.maxv, v);
if(l<r)
{
int m=l+r>>1;
if(p<=m) Insert(lson,p,v);
else Insert(rson,p,v);
}
}
int Query(int l,int r,int rt,int L,int R)
{
if(!rt) return 0;
if(L<=l && r<=R) return now.maxv;
int m=l+r>>1;
if(L<=m)
if(m<R) return std::max(Query(lson,L,R),Query(rson,L,R));
else return Query(lson,L,R);
return Query(rson,L,R);
}
}t;
struct Bit
{
int root[N];
void Insert(int p,int y,int v)
{
while(p<=MaxV)
t.Insert(1,MaxA,root[p],y,v), p+=lb(p);
}
int Query(int p,int y)
{
int res=0;
while(p)
res=std::max(res,t.Query(1,MaxA,root[p],1,y)), p-=lb(p);
return res;
}
}t2D;
}
#undef now
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
} int main()
{
n=read(),m=read();
for(int i=1; i<=n; ++i)
maxv[i]=minv[i]=A[i]=read(), MaxA=std::max(MaxA,A[i]);
for(int x,y,i=1; i<=m; ++i)
x=read(), y=read(), maxv[x]=std::max(maxv[x],y), minv[x]=std::min(minv[x],y);
for(int i=1; i<=n; ++i) MaxV=std::max(MaxV,maxv[i]);
int ans=0;
for(int v,i=1; i<=n; ++i)
{
v = Tree_2D::t2D.Query(minv[i],A[i]) + 1;
Tree_2D::t2D.Insert(A[i],maxv[i],v);
ans=std::max(ans,v);
}
printf("%d",ans); return 0;
}

二维线段树:

/*
BZOJ上直接MLE...洛谷P4093 4508ms(比Bit套Segtree慢3倍+) 293.33MB
空间消耗比较大 写指针吧。。
*/
#include<cstdio>
#include<cctype>
#include<algorithm>
#define gc() getchar()
#define lson l,m,rt->ls
#define rson m+1,r,rt->rs
const int N=1e5+5; int n,m,A[N],maxv[N],minv[N],MaxA,MaxV;
namespace Seg_Tree2D
{
struct Node
{
int maxv;
Node *ls,*rs;
Node(): maxv(0),ls(NULL),rs(NULL) { }
}pool[N<<7];//(logN)^2=256(2^8) 开得小点吧要不空间会炸
struct Node2D
{
Node *root;
Node2D *ls,*rs;
Node2D(): root(NULL),ls(NULL),rs(NULL) { }
}pool2D[N<<1],*root;
inline Node *new_Node()
{
static int cnt=0;
return &pool[cnt++];
}
inline Node2D *new_Node2D()
{
static int cnt=0;
return &pool2D[cnt++];
}
Node2D *Build(int l,int r)
{
Node2D *rt = new_Node2D();
if(l<r)
{
int m=l+r>>1;
rt->ls = Build(l,m);
rt->rs = Build(m+1,r);
}
return rt;
}
int Query(int l,int r,Node *rt,int L,int R)
{
if(!rt) return 0;
if(L<=l && r<=R) return rt->maxv;
int m=l+r>>1;
if(L<=m)
if(m<R) return std::max(Query(lson,L,R),Query(rson,L,R));
else return Query(lson,L,R);
return Query(rson,L,R);
}
int Query2D(int l,int r,Node2D *rt,int L,int R,int y1,int y2)
{
if(L<=l && r<=R) return Query(1,MaxA,rt->root,y1,y2);
int m=l+r>>1;
if(L<=m)
if(m<R) return std::max(Query2D(lson,L,R,y1,y2),Query2D(rson,L,R,y1,y2));
else return Query2D(lson,L,R,y1,y2);
return Query2D(rson,L,R,y1,y2);
}
void Insert(int l,int r,Node *&rt,int p,int v)
{
if(!rt) rt = new_Node();//!
rt->maxv = std::max(rt->maxv, v);
if(l<r)
{
int m=l+r>>1;
if(p<=m) Insert(lson,p,v);
else Insert(rson,p,v);
}
}
void Insert2D(int l,int r,Node2D *rt,int p,int y,int v)
{
Insert(1, MaxA, rt->root, y, v);
if(l<r)
{
int m=l+r>>1;
if(p<=m) Insert2D(lson,p,y,v);
else Insert2D(rson,p,y,v);
}
}
void Init()
{
root = Build(1,MaxV);
}
int Query_Max(int l,int r,int y1,int y2)
{
return Query2D(1,MaxV,root,l,r,y1,y2);
}
void Insert_Node(int x,int y,int v)
{
Insert2D(1,MaxV,root,x,y,v);
}
}
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
} int main()
{
n=read(),m=read();
for(int i=1; i<=n; ++i)
maxv[i]=minv[i]=A[i]=read(), MaxA=std::max(MaxA,A[i]);
for(int x,y,i=1; i<=m; ++i)
x=read(), y=read(), maxv[x]=std::max(maxv[x],y), minv[x]=std::min(minv[x],y);
for(int i=1; i<=n; ++i) MaxV=std::max(MaxV,maxv[i]);
Seg_Tree2D::Init();
int ans=0;
for(int v,i=1; i<=n; ++i)
{
v = Seg_Tree2D::Query_Max(1,minv[i],1,A[i]) + 1;
Seg_Tree2D::Insert_Node(A[i],maxv[i],v);
ans=std::max(ans,v);
}
printf("%d",ans); return 0;
}

BZOJ.4553.[HEOI2016&TJOI2016]序列(DP 树状数组套线段树/二维线段树(MLE) 动态开点)的更多相关文章

  1. tyvj P1716 - 上帝造题的七分钟 二维树状数组区间查询及修改 二维线段树

    P1716 - 上帝造题的七分钟 From Riatre    Normal (OI)总时限:50s    内存限制:128MB    代码长度限制:64KB 背景 Background 裸体就意味着 ...

  2. 洛谷 P4093: bzoj 4553: [HEOI2016/TJOI2016]序列

    题目传送门:洛谷P4093. 题意简述: 给定一个长度为 \(n\) 的序列 \(a\). 同时这个序列还可能发生变化,每一种变化 \((x_i,y_i)\) 对应着 \(a_{x_i}\) 可能变成 ...

  3. Luogu P4093 [HEOI2016/TJOI2016]序列 dp套CDQ

    题面 好久没写博客了..最近新学了CDQ...于是就来发一发一道CDQ的练习题 看上去就是可以dp的样子. 设\(dp_{i}\)为以i结尾的最长不下降序列. 易得:\(dp_{i}\)=\(max( ...

  4. 【BZOJ】1901: Zju2112 Dynamic Rankings(区间第k小+树状数组套主席树)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1901 首先还是吐槽时间,我在zoj交无限tle啊!!!!!!!!我一直以为是程序错了啊啊啊啊啊啊. ...

  5. [BZOJ 3295] [luogu 3157] [CQOI2011]动态逆序对(树状数组套权值线段树)

    [BZOJ 3295] [luogu 3157] [CQOI2011] 动态逆序对 (树状数组套权值线段树) 题面 给出一个长度为n的排列,每次操作删除一个数,求每次操作前排列逆序对的个数 分析 每次 ...

  6. BZOJ 1901 Zju2112 Dynamic Rankings ——树状数组套主席树

    [题目分析] BZOJ这个题目抄的挺霸气. 主席树是第一时间想到的,但是修改又很麻烦. 看了别人的题解,原来还是可以用均摊的思想,用树状数组套主席树. 学到了新的姿势,2333o(* ̄▽ ̄*)ブ [代 ...

  7. [BZOJ 3196] 213平衡树 【线段树套set + 树状数组套线段树】

    题目链接:BZOJ - 3196 题目分析 区间Kth和区间Rank用树状数组套线段树实现,区间前驱后继用线段树套set实现. 为了节省空间,需要离线,先离散化,这样需要的数组大小可以小一些,可以卡过 ...

  8. [BZOJ 1901] Dynamic Rankings 【树状数组套线段树 || 线段树套线段树】

    题目链接:BZOJ - 1901 题目分析 树状数组套线段树或线段树套线段树都可以解决这道题. 第一层是区间,第二层是权值. 空间复杂度和时间复杂度均为 O(n log^2 n). 线段树比树状数组麻 ...

  9. 【序列操作IV】树状数组套线段树/树套树

    题目描述 给出序列 a1,a2,…,an(0≤ai≤109),有关序列的两种操作. 1. ai(1≤i≤n)变成 x(0≤x≤109). 2. 求 al,al+1,…,ar(1≤l≤r≤n)第 k(1 ...

随机推荐

  1. 【转】shell编程下 特殊变量、test / [ ]判断、循环、脚本排错

    [转]shell编程下 特殊变量.test / [ ]判断.循环.脚本排错 第1章 shell中的特殊变量 1.1 $# $# 表示参数的个数 1.1.1 [示例]脚本内容 [root@znix ~] ...

  2. BN讲解(转载)

    本文转载自:http://blog.csdn.net/shuzfan/article/details/50723877 本次所讲的内容为Batch Normalization,简称BN,来源于< ...

  3. git安装及基础用法

    1.安装GitGit-2.9.3-64-bit.exe 2.打开Git Bash,设置用户名,Email $ git config --global user.name "Your Name ...

  4. eclipse引入系统类库

    引入系统类库1.第一步:项目,右键,build path,remove报错的类库 2.第二步:项目,右键,build path→Add Library→JRE System Library,Next3 ...

  5. (并发编程)进程 (multiprocessing--Process实现进程并发)

    ['创建进程2方式种', '进程对象属性:join方法,守护进程obj.daemon=True,obj.pid, obj.name, obj.terminate(),obj.is_alive()等 ' ...

  6. saltstack自动化运维系列⑥SaltStack实践安装配置HAproxy

    saltstack自动化运维系列⑥SaltStack实践安装配置HAproxy 下载haproxy1.6.2.tar.gz下载地址:http://www.haproxy.org/download/1. ...

  7. 配置mysql5.5主从复制、半同步复制、主主复制

    mysql主服务器 192.168.8.40 mysql从服务器 192.168.8.41 全新配置过程(主和从数据库都没有数据): 主从复制主服务器设置: 1.改server-id      2.启 ...

  8. php计算给定时间之前的函数

    这里给定一个时间,计算这个时间在多久前,比如:2天前,1年前 function prettyDate($date){ $time = strtotime($date); $now = time(); ...

  9. PHP获取文件大小的方法详解

    对于初入门的PHP新手来说,PHP获取文件大小这个功能实现,或许有一定的难度.但是相信新手小白们在看过本篇文章介绍后,一定能轻松掌握PHP获取文件大小的重要知识! 下面我们通过具体的代码示例,为大家详 ...

  10. django----数据库表设计

    设计表时注意的几点: 1. nid = models.AutoField(primary_key=True)        #如果不指定django会默认加上id的 nid = models.BigA ...