2021.12.07 [TJOI2013]最长上升子序列(Treap+DP)

https://www.luogu.com.cn/problem/P4309

题意:

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

分析:

对于第 \(i\) 个插进去的数字 \(i\) ,插到了第 \(x\) 位,则对于前 \(i\) 个数字的最长上升子序列 \(f[i]\) :

\[f[i]=\max(f[1]+1,f[2]+1,f[3]+1,\cdots,f[i-1]+1)\\
=\max(f[1],f[2],f[3],\cdots,f[i-1])+1
\]

所以只需要最后求一边最长上升子序列就行。

这里可以使用树状数组或者硬算。

插入那就按照子树大小分割,一步步插入就行。

注:如果想使用 \(M\times v_1+v_2\) 这个方法插入,这是不行滴~比如:我现在第一位插入,又在第一位插入,在第二位插入,在第一位插入。按照这个方法插入结果是 4 2 1 3 ,而真正结果是 4 2 3 1

代码如下:

0pts:

Treap+树状数组

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std; #define int long long
const int N=1e5+10;
int n,cnt,root,son[N][2],sizei[N],same[N],val[N],key[N],trueval[N];
int t[N]; inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')w=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0'){
s=s*10+ch-'0';
ch=getchar();
}
return s*w;
}
inline void update(int x){
sizei[x]=sizei[son[x][0]]+sizei[son[x][1]]+same[x];
}
inline void rotate(int &x,int flag){
int y=son[x][flag^1];
int change=son[y][flag];
son[x][flag^1]=change;
son[y][flag]=x;
update(x);
update(y);
x=y;
}
inline void insert(int &x,int vali,int truevali){
if(!x){
x=++cnt;
sizei[x]=same[x]=1;
val[x]=vali;
trueval[x]=truevali;
key[x]=rand();
return ;
}
if(val[x]==vali)return (void)(++sizei[x],++same[x]);
int flag=vali>val[x];
insert(son[x][flag],vali,truevali);
if(key[x]<key[son[x][flag]])rotate(x,flag^1);
update(x);
}
inline int rank_score(int x,int k){
if(!x)return 0;
if(sizei[son[x][0]]>=k)return rank_score(son[x][0],k);
else if(sizei[son[x][0]]+same[x]>=k)return trueval[x];
else return rank_score(son[x][1],k-sizei[son[x][0]]-same[x]);
}
inline int lowbit(int x){
return x&-x;
}
inline void add(int x,int k){
for(int i=x;i<=n;i+=lowbit(i))t[i]=max(t[i],k);
}
inline int query(int x){
int fin=0;
for(int i=x;i>0;i-=lowbit(i))fin=max(fin,t[i]);
return fin;
} signed main(){
n=read();
for(int i=1;i<=n;i++){
int x=read();
x=x*(N-10)-i;
insert(root,x,i);
}
for(int i=1;i<=n;i++){
int x=rank_score(root,i);
int y=query(x-1)+1;
//cout<<x<<" "<<y<<endl;
cout<<y<<endl;
add(x,y);
}
return 0;
}

100pts:

Treap+硬算

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std; #define int long long
const int N=1e5+10;
int n,cnt,root,son[N][2],sizei[N],same[N],val[N],key[N],trueval[N];
int t[N],a[N],ans[N],b[N],f[N]; inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')w=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0'){
s=s*10+ch-'0';
ch=getchar();
}
return s*w;
}
inline void update(int x){
sizei[x]=sizei[son[x][0]]+sizei[son[x][1]]+same[x];
}
inline void rotate(int &x,int flag){
int y=son[x][flag^1];
int change=son[y][flag];
son[x][flag^1]=change;
son[y][flag]=x;
update(x);
update(y);
x=y;
}
inline void insert(int &x,int vali,int truevali){
if(!x){
x=++cnt;
sizei[x]=same[x]=1;
val[x]=vali;
trueval[x]=truevali;
key[x]=rand();
return ;
}
int flag=0;
if(vali<=sizei[son[x][0]])insert(son[x][0],vali,truevali),flag=0;
else insert(son[x][1],vali-sizei[son[x][0]]-same[x],truevali),flag=1;
if(key[x]<key[son[x][flag]])rotate(x,flag^1);
update(x);
}
inline void work(int x){
if(son[x][0])work(son[x][0]);
a[++n]=trueval[x];
if(son[x][1])work(son[x][1]);
} signed main(){
n=read();
for(int i=1;i<=n;i++){
int x=read();
//x=x*(N-10)-i;
insert(root,x,i);
}
n=0;
work(root);
for(int i=1;i<=n;i++)b[i]=n+1;
//for(int i=1;i<=n;i++)cout<<a[i]<<" ";cout<<endl;//
for(int i=1;i<=n;i++){
int x=lower_bound(b,b+n+1,a[i])-b;
f[i]=x;
b[f[i]]=min(b[f[i]],a[i]);
ans[a[i]]=f[i];
//cout<<x<<" "<<ans[a[i]]<<endl;//
}
for(int i=1;i<=n;i++)ans[i]=max(ans[i],ans[i-1]);
for(int i=1;i<=n;i++)cout<<ans[i]<<endl;
return 0;
}

2021.12.07 [TJOI2013]最长上升子序列(Treap+DP)的更多相关文章

  1. 2021.12.07 P4291 [HAOI2008]排名系统(Treap)

    2021.12.07 P4291 [HAOI2008]排名系统(Treap) https://www.luogu.com.cn/problem/P4291 双倍经验: https://www.luog ...

  2. BZOJ 3173: [Tjoi2013]最长上升子序列 [splay DP]

    3173: [Tjoi2013]最长上升子序列 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1613  Solved: 839[Submit][St ...

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

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

  4. 【bzoj3173】[Tjoi2013]最长上升子序列 Treap

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

  5. bzoj 3173: [Tjoi2013]最长上升子序列【dp+线段树】

    我也不知道为什么把题看成以插入点为结尾的最长生生子序列--还WA了好几次 先把这个序列最后的样子求出来,具体就是倒着做,用线段树维护点数,最开始所有点都是1,然后线段树上二分找到当前数的位置,把这个点 ...

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

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

  7. BZOJ 3173: [Tjoi2013]最长上升子序列

    3173: [Tjoi2013]最长上升子序列 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1524  Solved: 797[Submit][St ...

  8. Bzoj 3173: [Tjoi2013]最长上升子序列 平衡树,Treap,二分,树的序遍历

    3173: [Tjoi2013]最长上升子序列 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1183  Solved: 610[Submit][St ...

  9. BZOJ 3173: [Tjoi2013]最长上升子序列( BST + LIS )

    因为是从1~n插入的, 慢插入的对之前的没有影响, 所以我们可以用平衡树维护, 弄出最后的序列然后跑LIS就OK了 O(nlogn) --------------------------------- ...

随机推荐

  1. Linux移植总结--uboot从不同介质上启动分析

    @ 目录 1.启动地址 2.uboot占用内存 3.2440从NAND启动 4.2440从NOR启动 5.某开发板从SPI FLASH启动 1.启动地址 先以2440开发板为例,SDRAM(0x300 ...

  2. ubuntu 16.04 设置root用户初始密码

    安装ubuntu成功后,都是普通用户权限,并没有最高root权限,如果需要使用root权限的时候,通常都会在命令前面加上 sudo .有的时候感觉很麻烦- 我们一般使用su命令来直接切换到root用户 ...

  3. luoguP4859 已经没有什么好害怕的了(二项式反演)

    luoguP4859 已经没有什么好害怕的了(二项式反演) 祭奠天国的bzoj. luogu 题解时间 先特判 $ n - k $ 为奇数无解. 为了方便下记 $ m = ( n + k ) / 2 ...

  4. luoguP6623 [省选联考 2020 A 卷] 树(trie树)

    luoguP6623 [省选联考 2020 A 卷] 树(trie树) Luogu 题外话: ...想不出来啥好说的了. 我认识的人基本都切这道题了. 就我只会10分暴力. 我是傻逼. 题解时间 先不 ...

  5. sem信号量与死锁的边缘

    1. 演示一个例子,出现死锁,用strace debug得到 #include<stdio.h> #include<pthread.h> #include<stdlib. ...

  6. manjaro下使用scrcpy安卓设备投屏

    scrcpy 安卓版本要大于等于 5.0 安装scrcpy及安卓工具包 yay -S scrcpy-git android-tools 打开手机 开发者模式->USB调试,将手机通过数据线连接电 ...

  7. Json有什么作用?

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式. 它基于JavaScript(Standard ECMA-262 3rd Edition - Decemb ...

  8. Kafka 缺点?

    由于是批量发送,数据并非真正的实时: 对于mqtt协议不支持: 不支持物联网传感数据直接接入: 仅支持统一分区内消息有序,无法实现全局消息有序: 监控不完善,需要安装插件: 依赖zookeeper进行 ...

  9. springmvc对前台参数的接收

    一.基本数据类型的接收 代码: @RequestMapping("/selectRegion") public BaseResult<?> method(String ...

  10. spring DAO 有什么用?

    Spring DAO 使得 JDBC,Hibernate 或 JDO 这样的数据访问技术更容易以一 种统一的方式工作.这使得用户容易在持久性技术之间切换.它还允许您在编写 代码时,无需考虑捕获每种技术 ...