Portal --> bzoj3173

Solution

  感觉自己需要智力康复qwq

  首先题目给的这个序列肯定是一个\(1-n\)的排列,并且插入的顺序是从小到大

  仔细思考一下会发现如果知道了最终的序列,问题就比较好解决了,这里提供一种用线段树的做法:

  如果知道了最终的序列,记数字\(i\)在该序列中的位置为\(loc[i]\),那么我们按照\(i\)从小到大的顺序,查询结尾在\([1,loc[i])\)的这段位置中的最长上升子序列的最大值\(mx\),并将\(mx+1\)作为以\(loc[i]\)位置为结尾的答案,插入到线段树中\(loc[i]\)对应的节点里,复杂度是\(O(nlogn)\)

  然后现在的问题是怎么求最终的序列

  这个可以用平衡树来写,不过其实也可以用线段树来写

  考虑反过来确定每一个数在最终序列中的位置,因为是反过来考虑的,所以一开始的时候每一个位置都有一个数,然后我们根据读入的插入位置,按照\(n-1\)的顺序,找到当前这个数的位置,然后将它删掉(也就是对应的线段树节点的\(sum-1\))

​  具体一点就是比如当前考虑到第\(i\)个数,读入这个数应该要插入在\(a[i]\)的位置后面,也就是应该在当前这个序列的第\(a[i]+1\)个位置,那么找到这个位置,然后把这个位置删掉,这样就可以得到还没有插入这个数之前的序列的位置集合了,这部分的复杂度也是\(O(nlogn)\)的

​  然后就十分愉快地做完啦

  

  代码大概长这个样子

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN=100010,SEG=MAXN*4;
namespace Seg{/*{{{*/
int ch[SEG][2],sum[SEG],mx[SEG];
int n,tot;
void pushup(int x){
sum[x]=sum[ch[x][0]]+sum[ch[x][1]];
mx[x]=max(mx[ch[x][0]],mx[ch[x][1]]);
}
void _build(int x,int l,int r){
sum[x]=0; mx[x]=0;
if (l==r){sum[x]=0; return;}
int mid=l+r>>1;
ch[x][0]=++tot; _build(ch[x][0],l,mid);
ch[x][1]=++tot; _build(ch[x][1],mid+1,r);
pushup(x);
}
void build(int _n){n=_n; tot=1; _build(1,1,n);}
void _update(int x,int d,int lx,int rx,int delta){
if (lx==rx) {sum[x]+=delta;mx[x]+=delta;return;}
int mid=lx+rx>>1;
if (d<=mid) _update(ch[x][0],d,lx,mid,delta);
else _update(ch[x][1],d,mid+1,rx,delta);
pushup(x);
}
void update(int d,int delta){_update(1,d,1,n,delta);}
int _query_mx(int x,int l,int r,int lx,int rx){
if (l<=lx&&rx<=r) return mx[x];
int mid=lx+rx>>1,ret=0;
if (l<=mid) ret=max(ret,_query_mx(ch[x][0],l,r,lx,mid));
if (r>mid) ret=max(ret,_query_mx(ch[x][1],l,r,mid+1,rx));
return ret;
}
int query(int l,int r){return _query_mx(1,l,r,1,n);}
int _get_loc(int x,int lx,int rx,int k){
if (lx==rx) return lx;
int mid=lx+rx>>1;
if (sum[ch[x][0]]>=k) return _get_loc(ch[x][0],lx,mid,k);
else return _get_loc(ch[x][1],mid+1,rx,k-sum[ch[x][0]]);
}
int get_loc(int k){return _get_loc(1,1,n,k);}
};/*}}}*/
int loc[MAXN],a[MAXN],b[MAXN];
int n,m,ans; int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
scanf("%d",&n);
for (int i=1;i<=n;++i) scanf("%d",b+i),++b[i];
Seg::build(n);
for (int i=1;i<=n;++i) Seg::update(i,1);
for (int i=n;i>=1;--i){
loc[i]=Seg::get_loc(b[i]);
Seg::update(loc[i],-1);
}
for (int i=1;i<=n;++i) a[loc[i]]=i; Seg::build(n);
ans=0;
int tmp;
for (int i=1;i<=n;++i){
if (loc[i]>1)
tmp=Seg::query(1,loc[i]-1);
else
tmp=0;
Seg::update(loc[i],tmp+1);
ans=max(ans,tmp+1);
printf("%d\n",ans);
}
}

【bzoj3173】最长上升子序列的更多相关文章

  1. [bzoj3173]最长上升子序列_非旋转Treap

    最长上升子序列 bzoj-3173 题目大意:有1-n,n个数,第i次操作是将i加入到原有序列中制定的位置,后查询当前序列中最长上升子序列长度. 注释:1<=n<=10,000,开始序列为 ...

  2. [BZOJ3173]最长上升子序列

    Problem 给你n个数A1~An,每次将i插入第Ai位后,最后输出每次插入后这个数列的最长上升子序列 Solution 这道题非常的妙.首先如果新加入的这个数构成了最长上升子序列,由于在它插入之前 ...

  3. [BZOJ3173][Tjoi2013]最长上升子序列

    [BZOJ3173][Tjoi2013]最长上升子序列 试题描述 给定一个序列,初始为空.现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置.每插入一个数字,我们都想知道此时最长上 ...

  4. 【LG4309】【BZOJ3173】[TJOI2013]最长上升子序列

    [LG4309][BZOJ3173][TJOI2013]最长上升子序列 题面 洛谷 BZOJ 题解 插入操作显然用平衡树就行了 然后因为后面的插入对前面的操作无影响 就直接在插入完的序列上用树状数组求 ...

  5. BZOJ3173 TJOI2013最长上升子序列(Treap+ZKW线段树)

    传送门 Description 给定一个序列,初始为空.现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置.每插入一个数字,我们都想知道此时最长上升子序列长度是多少? Input ...

  6. bzoj3173[Tjoi2013]最长上升子序列 平衡树+lis

    3173: [Tjoi2013]最长上升子序列 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2253  Solved: 1136[Submit][S ...

  7. bzoj千题计划316:bzoj3173: [Tjoi2013]最长上升子序列(二分+树状数组)

    https://www.lydsy.com/JudgeOnline/problem.php?id=3173 插入的数是以递增的顺序插入的 这说明如果倒过来考虑,那么从最后一个插入的开始删除,不会对以某 ...

  8. BZOJ3173:[TJOI2013]最长上升子序列(Splay)

    Description 给定一个序列,初始为空.现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置.每插入一个数字,我们都想知道此时最长上升子序列长度是多少? Input 第一行一 ...

  9. bzoj3173: [Tjoi2013]最长上升子序列(fhqtreap)

    这题用fhqtreap可以在线. fhqtreap上维护以i结尾的最长上升子序列,数字按从小到大加入, 因为前面的数与新加入的数无关, 后面的数比新加入的数小, 所以新加入的数对原序列其他数的值没有影 ...

随机推荐

  1. Spring 定时任务Scheduled 开发详细图文

    Spring 定时任务Scheduled 开发 文章目录 一.前言 1.1 定时任务 1.2 开发环境 1.3 技术实现 二.创建包含WEB.xml 的Maven 项目 2.1 创建多模块项目task ...

  2. HADOOP操作权限问题

    hdfs的权限判断十分简单,就是拿发出指令的user name和文件的user name 做比较   private void check(INode inode, FsAction access   ...

  3. Windows 下在 Python (Anaconda) 中安装 Dlib 库

    0. 引言 介绍在 Windows  操作系统下,在 Python 的 Anaconda 集成环境中,安装 Dlib 库 : 对于不了解源码编译的,或者利用 cmake 方法失败的,可以尝试下此方法: ...

  4. JAVA学习笔记--数组初始化

    JAVA中,数组只是相同类型的.用一个标识符名称封装到一起的一个对象序列或基本类型数据序列.数组通过方括号下标操作符[]来定义和使用,要定义一个数组只需在类型名后面加上一个方括号即可,如: int[] ...

  5. hadoop之mapper类妙用

    1. Mapper类 首先 Mapper类有四个方法: (1) protected void setup(Context context) (2) Protected void map(KEYIN k ...

  6. NO.1:自学python之路------Hello world、判断、循环

    引言 人工智能如今越来越贴近生活,在这里将记录我自学python与tensorflow的过程.编程使用IDE:visual studio 2017,python版本3.6.4,tensorflow版本 ...

  7. java-HttpGetPost-图片字节流上传

    在java程序开发中经常用到与服务端的交互工作,主要的就是传递相应的参数请求从而获取到对应的结果加以处理 可以使用Get请求与Post请求,注意!这里的Get请求不是通过浏览器界面而是在程序代码中设置 ...

  8. centos上搭建git服务--4

    Git是目前世界上最先进的分布式版本控制系统(没有之一).使用Svn的请参考<版本控制-svn服务器搭建和常用命令(centos 6.3)>,下面介绍Git的常用命令 常用命令 简单版 升 ...

  9. 欢迎来怼---作业要求 20171015 beta冲刺贡献分分配规则

    一.小组信息 队名:欢迎来怼 小组成员 队长:田继平 成员:李圆圆,葛美义,王伟东,姜珊,邵朔,阚博文 基础分      每人占个人总分的百分之40% leangoo里面的得分    每人占个人总分里 ...

  10. Spring1()

    目的: 降低Java开发的复杂性 使用策略: 基于POJO的轻量级和最小侵入式的编程 通过依赖注入和面向接口实现松耦合 基于切面和惯例进行声明式编程 通过切面和模版减少样式代码 依赖注入:由Sprin ...