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. Python GUI tkinter 学习笔记(三)

    草稿 # -*- coding: utf-8 -*- from Tkinter import * root = Tk() Label(root, text = "First").g ...

  2. toppo-1

    靶机准备 由于是.vmdk文件,新建一个虚拟机把硬盘移除,在将此vmdk文件添加为新硬盘即. 开机发现给出了ip地址:192.168.164.184,且当前网络模式为NAT 将kali也设置为NAT模 ...

  3. Linux下swap(交换分区)的增删改

    swap介绍 Linux 的交换分区(swap),或者叫内存置换空间(swap space),是磁盘上的一块区域,可以是一个分区,也可以是一个文件,或者是他们的组合.交换分区的作用是,当系统物理内存吃 ...

  4. 常见的反爬措施:UA反爬和Cookie反爬

    摘要:为了屏蔽这些垃圾流量,或者为了降低自己服务器压力,避免被爬虫程序影响到正常人类的使用,开发者会研究各种各样的手段,去反爬虫. 本文分享自华为云社区<Python爬虫反爬,你应该从这篇博客开 ...

  5. 把项目发布到tomcat中的方式

    1.相对路径方式1:把项目index.html放在tomcat的webapps/ROOT下,浏览器访问地址:http://www.aaa.com:8080/index.html 2.相对路径方式2:在 ...

  6. LCS&&LRC&&LIS问题

    注:最近笔试题经常碰到DP动态规划的问题,但是由于本人没有接触过DP,笔试后看到别人家的答案简洁又漂亮,真的羡慕:难的DP自己可能不会,那再见到常见的LCS和LRS以及LIS为问题总该会吧: 资料参考 ...

  7. 是否可以从一个static方法内部调用非static方法?

    不可以.静态成员不能调用非静态成员. 非static方法属于对象,必须创建一个对象后,才可以在通过该对象来调用static方法.而static方法调用时不需要创建对象,通过类就可以调用该方法.也就是说 ...

  8. 什么情况下一个 broker 会从 isr中踢出去?

    leader会维护一个与其基本保持同步的Replica列表,该列表称为ISR(in-sync Replica),每个Partition都会有一个ISR,而且是由leader动态维护 ,如果一个foll ...

  9. java-IO异常处理

    以前的异常处理 public class Demo3 { public static void main(String[] args) { //提高fw的作用域 //变量定义的时候可以没有值,但是使用 ...

  10. (原创)[C#] 一步一步自定义拖拽(Drag&Drop)时的鼠标效果:(一)基本原理及基本实现

    一.前言 拖拽(Drag&Drop),属于是极其常用的基础功能. 无论是在系统上.应用上.还是在网页上,拖拽随处可见.同时拖拽时的鼠标效果也很漂亮,像这样: 这样: 还有这样: 等等等等. 这 ...