[BZOJ 3173] [TJOI 2013] 最长上升子序列(fhq treap)
[BZOJ 3173] [TJOI 2013] 最长上升子序列(fhq treap)
题面
给定一个序列,初始为空。现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置。每插入一个数字,我们都想知道此时最长上升子序列长度是多少?
分析
这题有几个重要性质:
第一个性质是,插入的数的大小是递增的。我们插入第i个数后的答案,为以当前序列中的数为结尾的LIS长度的最大值,而根据当前序列中的数都在[1,i]内,们可以维护以值v为结尾的LIS长度len[i],那么第i次插入后的答案就是\(max(len[j]) (j \in [1,i])\)
第二个性质是,后插入的数不会影响以前面插入的数为结尾的LIS长度。这句话有点抽象,我们来举一个例子。插入完两个数后的序列是{1,2},以2结尾的LIS长度为2。然后我们在2前面插入3,序列变成了{1,3,2},因为3>2,它不会影响以2结尾的LIS长度,因此以2结尾的LIS长度仍为2。如果插入在2后面,显然新的LIS结尾不可能是2,对以2结尾的LIS长度没有影响。
因此,我们只要用一个数据结构处理出插入n次后的最终序列,对这个序列跑一次LIS,求出以v结尾的序列长度,然后前缀max一下求出答案。这里我选择了fhq treap来维护序列,然后用模板的\(O(n \log n)\)求LIS算法。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#define maxn 100000
using namespace std;
struct fhq_treap{
#define lson(x) tree[x].ls
#define rson(x) tree[x].rs
	struct node{
		int ls;
		int rs;
		int val;
		int sz;
		int dat;
	}tree[maxn+5];
	int root;
	int ptr;
	int New(int val){
		ptr++;
		tree[ptr].val=val;
		tree[ptr].dat=rand();
		tree[ptr].sz=1;
		return ptr;
	}
	void push_up(int x){
		tree[x].sz=tree[lson(x)].sz+tree[rson(x)].sz+1;
	}
	int merge(int x,int y){
		if(!x||!y) return x+y;
		if(tree[x].dat<tree[y].dat){
			tree[y].ls=merge(x,tree[y].ls);
			push_up(y);
			return y;
		}else{
			tree[x].rs=merge(tree[x].rs,y);
			push_up(x);
			return x;
		}
	}
	void split(int now,int k,int &x,int &y){
		if(now==0){
			x=y=0;
			return;
		}
		if(k<=tree[lson(now)].sz){
			y=now;
			split(tree[now].ls,k,x,tree[y].ls);
		}else{
			x=now;
			split(tree[now].rs,k-tree[lson(now)].sz-1,tree[x].rs,y);
		}
		push_up(now);
	}
	void insert(int val,int pos){
		int x,y;
		split(root,pos-1,x,y);
		root=merge(merge(x,New(val)),y);
	}
	void print(int x,int *out,int &sz){
		if(x==0) return;
		print(lson(x),out,sz);
		out[++sz]=tree[x].val;
		print(rson(x),out,sz);
	}
}T;
int n;
int sz=0;
int a[maxn+5];
int top=0;
int s[maxn+5];
int len[maxn+5];//以值i为结尾的LIS长度
void get_lis(){
	for(int i=1;i<=n;i++){
		if(a[i]>s[top]){
			s[++top]=a[i];
			len[a[i]]=top;
		}else{
			int tmp=lower_bound(s+1,s+1+top,a[i])-s;
			s[tmp]=a[i];
			len[a[i]]=tmp;
		}
	}
}
int main(){
	int x;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&x);
		x++;
		T.insert(i,x);
	}
	T.print(T.root,a,sz);
//	for(int i=1;i<=sz;i++) printf("%d ",a[i]);
	get_lis();
	int ans=0;
	for(int i=1;i<=n;i++){
		ans=max(ans,len[i]);
		printf("%d\n",ans);
		//第i个数插入的时候,序列里只有1~i的数,把以它们为结尾的lis长度取max即可
	}
}
												
											[BZOJ 3173] [TJOI 2013] 最长上升子序列(fhq treap)的更多相关文章
- 【bzoj 3173】[Tjoi2013]最长上升子序列
		
Description 给定一个序列,初始为空.现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置.每插入一个数字,我们都想知道此时最长上升子序列长度是多少? Input 第一行一 ...
 - [TJOI]2013 最长上升子序列
		
这个题据说是Splay,或者说是平衡树的模板题,但是我还是不会做--唉-- \(\color{red}{Description}\) 给定一个序列,初始为空.现在我们将\(1\)到\(N\)的数字插入 ...
 - 2021.12.07 [TJOI2013]最长上升子序列(Treap+DP)
		
2021.12.07 [TJOI2013]最长上升子序列(Treap+DP) https://www.luogu.com.cn/problem/P4309 题意: 给定一个序列,初始为空.现在我们将1 ...
 - Bzoj 3173: [Tjoi2013]最长上升子序列  平衡树,Treap,二分,树的序遍历
		
3173: [Tjoi2013]最长上升子序列 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1183 Solved: 610[Submit][St ...
 - bzoj 3173 [Tjoi2013]最长上升子序列 (treap模拟+lis)
		
[Tjoi2013]最长上升子序列 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2213 Solved: 1119[Submit][Status] ...
 - BZOJ 3170: [Tjoi 2013]松鼠聚会  切比雪夫距离
		
3170: [Tjoi 2013]松鼠聚会 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/p ...
 - BZOJ 3170: [Tjoi 2013]松鼠聚会( sort )
		
题目的距离为max(|x1-x2|, |y1-y2|) (切比雪夫距离). 切比雪夫距离(x, y)->曼哈顿距离((x+y)/2, (x-y)/2) (曼哈顿(x, y)->切比雪夫(x ...
 - Bzoj 3170[Tjoi 2013]松鼠聚会 曼哈顿距离与切比雪夫距离
		
3170: [Tjoi 2013]松鼠聚会 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1318 Solved: 664[Submit][Stat ...
 - 【bzoj3173】【Tjoi2013】【最长上升子序列】treap+dp二分优化
		
[pixiv] https://www.pixiv.net/member_illust.php?mode=medium&illust_id=61560361 向大(hei)佬(e)实力学(di ...
 
随机推荐
- 唤醒 App
			
一.Deep Link 1.什么是 Deep Link? Deep Link 是 App 的深度连接,当单击链接或编程请求调用Web URI意图时,Android系统按顺序依次尝试以下每一个操作,直到 ...
 - angularJS拖动marker时popup一直显示
			
$scope.$on('leafletDirectiveMarker.drag', function(event, arg) { arg.leafletObject.openPopup(); });
 - springboot自定义异常视图
			
一.源码分析 先看源码再写自己的自定义异常视图 resolveErrorView()函数首先调用了一个返回ModelAndView的函数,该函数所需的参数是一个状态码的字符串,和一个m ...
 - 同样是1ms子帧,为什么5G的时延比LTE小得多
			
转载:http://www.txrjy.com/forum.php?mod=viewthread&tid=1045092 个子帧中一定包含14个OFDM符号.当子载波间隔是15KHz时,1个5 ...
 - 容器镜像服务 联手 IDE 插件,实现一键部署、持续集成与交付
			
容器技术提供了一种标准化的交付方式,将应用的代码以及代码环境依赖都打包在一起,成为一个与环境无关的交付物,可以被用在软件生命周期的任何阶段,彻底改变了传统的软件交付方式. 甚至可以说,是在容器技术之后 ...
 - computed属性和watcher
			
computed属性 在模板中使用表达式是非常方便直接的,然而这只适用于简单的操作.在模板中放入太多的逻辑,会使模板过度膨胀和难以维护.例如: <div id="example&quo ...
 - 13-1 jquery操作cookie
			
jQuery之cookie操作 Cookies 定义:让网站服务器把少量数据存储到客户端的硬盘或内存,从客户端的硬盘里读取数据的一种技术; 下载与引入:jquery.cookie.js基于jquery ...
 - 高通 8x26 andorid light sensor(TSL258x) 开发【转】
			
本文转载自:http://www.voidcn.com/blog/u012296694/article/p-1669831.html 前言 8926平台的sensor架构与之前的平台完全不同,实际上已 ...
 - 爬虫 ---- BeautifulSoup的基础使用
			
#BeautifulSoup的基础使用from bs4 import BeautifulSoup #导入bs4库 html = "<p class='stylecss'>< ...
 - 软件-工具:Beyond Compare
			
ylbtech-软件-工具:Beyond Compare 1.返回顶部 1. Beyond Compare是一套由Scooter Software推出的文件比较工具.主要用途是对比两个文件夹或者文件, ...