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[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) 动态开点)的更多相关文章
- tyvj P1716 - 上帝造题的七分钟 二维树状数组区间查询及修改 二维线段树
P1716 - 上帝造题的七分钟 From Riatre Normal (OI)总时限:50s 内存限制:128MB 代码长度限制:64KB 背景 Background 裸体就意味着 ...
- 洛谷 P4093: bzoj 4553: [HEOI2016/TJOI2016]序列
题目传送门:洛谷P4093. 题意简述: 给定一个长度为 \(n\) 的序列 \(a\). 同时这个序列还可能发生变化,每一种变化 \((x_i,y_i)\) 对应着 \(a_{x_i}\) 可能变成 ...
- Luogu P4093 [HEOI2016/TJOI2016]序列 dp套CDQ
题面 好久没写博客了..最近新学了CDQ...于是就来发一发一道CDQ的练习题 看上去就是可以dp的样子. 设\(dp_{i}\)为以i结尾的最长不下降序列. 易得:\(dp_{i}\)=\(max( ...
- 【BZOJ】1901: Zju2112 Dynamic Rankings(区间第k小+树状数组套主席树)
http://www.lydsy.com/JudgeOnline/problem.php?id=1901 首先还是吐槽时间,我在zoj交无限tle啊!!!!!!!!我一直以为是程序错了啊啊啊啊啊啊. ...
- [BZOJ 3295] [luogu 3157] [CQOI2011]动态逆序对(树状数组套权值线段树)
[BZOJ 3295] [luogu 3157] [CQOI2011] 动态逆序对 (树状数组套权值线段树) 题面 给出一个长度为n的排列,每次操作删除一个数,求每次操作前排列逆序对的个数 分析 每次 ...
- BZOJ 1901 Zju2112 Dynamic Rankings ——树状数组套主席树
[题目分析] BZOJ这个题目抄的挺霸气. 主席树是第一时间想到的,但是修改又很麻烦. 看了别人的题解,原来还是可以用均摊的思想,用树状数组套主席树. 学到了新的姿势,2333o(* ̄▽ ̄*)ブ [代 ...
- [BZOJ 3196] 213平衡树 【线段树套set + 树状数组套线段树】
题目链接:BZOJ - 3196 题目分析 区间Kth和区间Rank用树状数组套线段树实现,区间前驱后继用线段树套set实现. 为了节省空间,需要离线,先离散化,这样需要的数组大小可以小一些,可以卡过 ...
- [BZOJ 1901] Dynamic Rankings 【树状数组套线段树 || 线段树套线段树】
题目链接:BZOJ - 1901 题目分析 树状数组套线段树或线段树套线段树都可以解决这道题. 第一层是区间,第二层是权值. 空间复杂度和时间复杂度均为 O(n log^2 n). 线段树比树状数组麻 ...
- 【序列操作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 ...
随机推荐
- windows系统中搭建Jenkins服务器
1 须知 100.126.36.232等Jenkins服务器是通过设置代理访问外网,管理Jenkins和插件升级站点的,本地安装受黄区网络限制需要特殊配置,且有些插件无法下载. 前提条件: ...
- tomcat启动报错 ERROR o.a.catalina.session.StandardManager 182 - Exception loading sessions from persiste
系统:centos6.5 x86_64 jdk: 1.8.0_102 tomcat:8.0.37 tomcat 启动报错: ERROR o.a.catalina.session.StandardMan ...
- html中子界面与父界面相互操作或传值
一.在使用iframe的页面,要操作这个iframe里面的DOM元素可以用: contentWindow.contentDocument(测试的时候chrom浏览器,要在服务器环境下) content ...
- OCM_第十九天课程:Section9 —》Data Guard _ DATA GUARD 原理/DATA GUARD 应用/DATA GUARD 搭建
注:本文为原著(其内容来自 腾科教育培训课堂).阅读本文注意事项如下: 1:所有文章的转载请标注本文出处. 2:本文非本人不得用于商业用途.违者将承当相应法律责任. 3:该系列文章目录列表: 一:&l ...
- php 中使用include、require、include_once、require_once的区别
在PHP中,我们经常会通过include.require.include_once.require_once来引用文件,都可以达到引用文件的目的,但他们之间又有哪些区别呢,接一下我们详细的介绍一下 i ...
- poj2342 没有上司的舞会 树形dp基础
#include<iostream> #include<cstring> #include<cstdio> #include<vector> using ...
- LINQ学习之旅 (四)
LINQ to SQL语句之Group By/Having和Exists/In/Any/All/Contains 1.Group By/Having操作符 适用场景:分组数据,为我们查找数据缩小范围. ...
- 【C++ Primer 第13章】5. 动态内存管理类
StrVec类的设计 [题目描述]:我们将实现标准库vector类的一个简化版本,我们所做的一个简化是不使用模板,我们类只用于string,因此,它被命名为StrVec. #include<io ...
- 浅析微信支付:公众平台卡券功能开通、HTML5线上发券(JS-SDK接口)、查看卡券详情
本文是[浅析微信支付]系列文章的第十六篇,主要讲解如何使用微信公众平台的卡券功能.如何使用HTML5在网页展示用户领券以及微信卡券和商户平台代金券的关系. 浅析微信支付系列已经更新十六篇了哟-,没有看 ...
- Java 和 C++ 的部分区别
1. Java是解释型语言,所谓的解释型语言,就是源码会先经过一次编译,成为中间码,中间码再被解释器解释成机器码.对于Java而言,中间码就是字节码(.class),而解释器在JVM中内置了. 2. ...