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. 对路径“C:\inetpub\wwwroot\Test\Temper\”的访问被拒绝 【已解决】

    在IIS7上部署IIS站点时,出现如下错误: 对路径"C:\inetpub\wwwroot\Test\Temper\"的访问被拒绝: 原因是:程序对"C:\inetpub ...

  2. bash shell 中的 hash 命令有什么作用?

    linux 命令'hash'管理着一个内置的哈希表,记录了已执行过的命令的完整路径,用该命令可以打印出你所使用过的命令以及执行的次数. [root@localhost ~]# hashhits com ...

  3. spring源码-扩展点

    /** * @Author quan * @Date 2020/11/13 * 扩展原理 * BeanPostProcessor bean后置处理器,bean创建对象初始化前后进行拦截工作 * * * ...

  4. kafka的message格式是什么样的?

    一个Kafka的Message由一个固定长度的header和一个变长的消息体body组成 header部分由一个字节的magic(文件格式)和四个字节的CRC32(用于判断body消息体是否正常)构成 ...

  5. FiddlerEverywhere注册账号进行激活失效问题

    有关FiddlerEverywhere通过邮件激活账号时,激活链接提示已失效问题:这个链接有进行一个讨论(https://www.telerik.com/forums/unable-to-activa ...

  6. 如何用 Java 代码列出一个目录下所有的文件?

    如果只要求列出当前文件夹下的文件,代码如下所示: import java.io.File; class Test12 { public static void main(String[] args) ...

  7. CopyOnWriteArrayList 可以用于什么应用场景?

    CopyOnWriteArrayList(免锁容器)的好处之一是当多个迭代器同时遍历和修改这 个列表时,不会抛出 ConcurrentModificationException.在 CopyOnWri ...

  8. String、StringBuiler、StringBuffer的区别

    一.三者的区别概述 1.可变与不可变:String底层使用final修饰的字符数组来存储字符串,它属于不可变类,对String对象的任何改变操作都不会改变原对象,而是生成一个新对象.StringBui ...

  9. 为什么 redis 需要把所有数据放到内存中?

    答Redis 为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数 据写入磁盘.所以 redis 具有快速和数据持久化的特征.如果不将数据放在内存中, 磁盘 I/O 速度为严重影响 redi ...

  10. ModelSerializer序列化器实战

    目录 ModelSerializer序列化器实战 单表操作 序列化器类 视图类 路由 模型 多表操作 models.py serializer.py views.py urls.py ModelSer ...