[BZOJ3173][Tjoi2013]最长上升子序列
[BZOJ3173][Tjoi2013]最长上升子序列
试题描述
输入
输出
输入示例
输出示例
数据规模及约定
100%的数据 n<=100000
题解
首先讲一下怎么找到插入的位置,不难发现输入的数 k 就是让我们找到一个位置使得该位置左边有 k 个数然后在这个位置上插入。这不就是“第 k 大数”问题么?
好的,在此基础之上,我们再在 treap 上维护一波子树最大权值即可。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <set>
using namespace std; int read() {
int x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
} #define maxn 100010
struct Node {
int r, val, mx, siz;
Node() {}
Node(int _, int __): r(_), val(__) {}
} ns[maxn];
int rt, ToT, fa[maxn], ch[2][maxn];
void maintain(int o) {
ns[o].mx = ns[o].val; ns[o].siz = 1;
for(int i = 0; i < 2; i++) if(ch[i][o])
ns[o].mx = max(ns[o].mx, ns[ch[i][o]].mx),
ns[o].siz += ns[ch[i][o]].siz;
return ;
}
void rotate(int u) {
int y = fa[u], z = fa[y], l = 0, r = 1;
if(z) ch[ch[1][z]==y][z] = u;
if(ch[1][y] == u) swap(l, r);
fa[u] = z; fa[y] = u; fa[ch[r][u]] = y;
ch[l][y] = ch[r][u]; ch[r][u] = y;
maintain(y); maintain(u);
return ;
}
void insert(int& o, int k, int val) {
if(!o) {
ns[o = ++ToT] = Node(rand(), val);
return maintain(o);
}
int ls = ch[0][o] ? ns[ch[0][o]].siz : 0;
bool d = (k >= ls + 1);
insert(ch[d][o], k - (ls + 1) * d, val); fa[ch[d][o]] = o;
if(ns[ch[d][o]].r > ns[o].r) {
int t = ch[d][o];
rotate(t); o = t;
}
return maintain(o);
}
int Find(int o, int k) {
if(!o) return 0;
int lm = ch[0][o] ? ns[ch[0][o]].mx : 0, ls = ch[0][o] ? ns[ch[0][o]].siz : 0;
if(k >= ls + 1) return max(max(lm, ns[o].val), Find(ch[1][o], k - ls - 1));
return Find(ch[0][o], k);
} int main() {
int n = read();
for(int i = 1; i <= n; i++) {
int p = read(), v = Find(rt, p);
insert(rt, p, v + 1);
printf("%d\n", ns[rt].mx);
} return 0;
}
替罪羊树版:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <set>
using namespace std; const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *Tail;
inline char Getchar() {
if(Head == Tail) {
int l = fread(buffer, 1, BufferSize, stdin);
Tail = (Head = buffer) + l;
}
return *Head++;
}
int read() {
int x = 0, f = 1; char c = Getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
return x * f;
} #define maxn 100010
struct Node {
int v, siz, mx;
Node() {}
Node(int _): v(_) {}
} ns[maxn];
int rt, ToT, fa[maxn], ch[maxn][2];
void maintain(int o) {
ns[o].siz = 1; ns[o].mx = ns[o].v;
for(int i = 0; i < 2; i++) if(ch[o][i])
ns[o].siz += ns[ch[o][i]].siz,
ns[o].mx = max(ns[o].mx, ns[ch[o][i]].mx);
return ;
}
const double Bili = .6;
bool unbal(int o) {
return max(ch[o][0] ? ns[ch[o][0]].siz : 0, ch[o][1] ? ns[ch[o][1]].siz : 0) > Bili * ns[o].siz;
}
int rb;
void insert(int& o, int k, int v) {
if(!o) {
ns[o = ++ToT] = Node(v);
return maintain(o);
}
int ls = ch[o][0] ? ns[ch[o][0]].siz : 0;
if(k < ls + 1) insert(ch[o][0], k, v), fa[ch[o][0]] = o;
else insert(ch[o][1], k - ls - 1, v), fa[ch[o][1]] = o;
maintain(o);
if(unbal(o)) rb = o;
return ;
}
int cntn, get[maxn];
void getnode(int o) {
if(!o) return ;
getnode(ch[o][0]);
get[++cntn] = o;
getnode(ch[o][1]);
fa[o] = ch[o][0] = ch[o][1] = 0;
return ;
}
void build(int& o, int l, int r) {
if(l > r) return ;
int mid = l + r >> 1; o = get[mid];
build(ch[o][0], l, mid - 1); build(ch[o][1], mid + 1, r);
if(ch[o][0]) fa[ch[o][0]] = o;
if(ch[o][1]) fa[ch[o][1]] = o;
return maintain(o);
}
void rebuild(int& o) {
cntn = 0; getnode(o);
build(o, 1, cntn);
return ;
}
void Insert(int k, int v) {
rb = 0; insert(rt, k, v);
if(!rb) return ;
int frb = fa[rb];
if(!frb) rebuild(rt), fa[rt] = 0;
else if(ch[frb][0] == rb) rebuild(ch[frb][0]), fa[ch[frb][0]] = frb;
else rebuild(ch[frb][1]), fa[ch[frb][1]] = frb;
return ;
}
int qmx(int o, int k) {
if(!o) return 0;
int ls = ch[o][0] ? ns[ch[o][0]].siz : 0, lm = ch[o][0] ? ns[ch[o][0]].mx : 0;
if(k < ls + 1) return qmx(ch[o][0], k);
return max(max(lm, ns[o].v), qmx(ch[o][1], k - ls - 1));
} int main() {
int n = read();
for(int i = 1; i <= n; i++) {
int pos = read(), tmp = qmx(rt, pos);
Insert(pos, tmp + 1);
printf("%d\n", qmx(rt, i + 1));
} return 0;
}
[BZOJ3173][Tjoi2013]最长上升子序列的更多相关文章
- bzoj3173[Tjoi2013]最长上升子序列 平衡树+lis
3173: [Tjoi2013]最长上升子序列 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2253 Solved: 1136[Submit][S ...
- bzoj3173: [Tjoi2013]最长上升子序列(树状数组+二分倒推)
3173: [Tjoi2013]最长上升子序列 题目:传送门 题解: 好题! 怎么说吧...是应该扇死自己...看错了两次题: 每次加一个数的时候,如果当前位置有数了,是要加到那个数的前面,而不是直 ...
- BZOJ3173 TJOI2013最长上升子序列(Treap+ZKW线段树)
传送门 Description 给定一个序列,初始为空.现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置.每插入一个数字,我们都想知道此时最长上升子序列长度是多少? Input ...
- bzoj千题计划316:bzoj3173: [Tjoi2013]最长上升子序列(二分+树状数组)
https://www.lydsy.com/JudgeOnline/problem.php?id=3173 插入的数是以递增的顺序插入的 这说明如果倒过来考虑,那么从最后一个插入的开始删除,不会对以某 ...
- BZOJ3173:[TJOI2013]最长上升子序列(Splay)
Description 给定一个序列,初始为空.现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置.每插入一个数字,我们都想知道此时最长上升子序列长度是多少? Input 第一行一 ...
- bzoj3173: [Tjoi2013]最长上升子序列(fhqtreap)
这题用fhqtreap可以在线. fhqtreap上维护以i结尾的最长上升子序列,数字按从小到大加入, 因为前面的数与新加入的数无关, 后面的数比新加入的数小, 所以新加入的数对原序列其他数的值没有影 ...
- BZOJ3173 TJOI2013最长上升子序列(splay)
容易发现如果求出最后的序列,只要算一下LIS就好了.序列用平衡树随便搞一下,这里种一棵splay. #include<iostream> #include<cstdio> #i ...
- 【LG4309】【BZOJ3173】[TJOI2013]最长上升子序列
[LG4309][BZOJ3173][TJOI2013]最长上升子序列 题面 洛谷 BZOJ 题解 插入操作显然用平衡树就行了 然后因为后面的插入对前面的操作无影响 就直接在插入完的序列上用树状数组求 ...
- BZOJ 3173: [Tjoi2013]最长上升子序列
3173: [Tjoi2013]最长上升子序列 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1524 Solved: 797[Submit][St ...
随机推荐
- Java正则抓取email
实现思路 1.使用Java.net.URL对象,绑定网络上某一个网页的地址 2.通过java.net.URL对象的openConnection()方法获得一个HttpConnection对象 3.通过 ...
- Spring多种注入方式及注解实现DI
一.Bean作用域 spring容器创建的时候,会将所有配置的bean对象创建出来,默认bean都是单例的.代码通过getBean()方法从容器获取指定的bean实例,容器首先会调用Bean类的无参构 ...
- C# 把日期字符串转换为日期类型 (MM大写为月、小写为分钟)
string dtStr; DateTime dtTime; 尝试把时间字符串转为DateTime格式 if (DateTime.TryParse(dtStr, out dtTime)) { //st ...
- 深入理解JVM内幕(转)
转自:http://blog.csdn.net/zhoudaxia/article/details/26454421/ 每个Java开发者都知道Java字节码是执行在JRE((Java Runtime ...
- 阻止事件冒泡,阻止默认事件,event.stopPropagation()和event.preventDefault(),return fal的区别
今天来看看前端的冒泡和事件默认事件如何处理 1.event.stopPropagation()方法 这是阻止事件的冒泡方法,不让事件向documen上蔓延,但是默认事件任然会执行,当你掉用这个方法的时 ...
- 2016年iOS笔试题
收集了一些ios面试的一些基础的试题,其中也有一些较难的 1.请简述UIView与CALayer有什么不同.2.Block什么情况下会保留实体内引用到外部对象,什么时候要用__block或__weak ...
- JS组件系列——Bootstrap Table 表格行拖拽(二:多行拖拽)
前言:前天刚写了篇JS组件系列——Bootstrap Table 表格行拖拽,今天接到新的需要,需要在之前表格行拖拽的基础上能够同时拖拽选中的多行.博主用了半天时间研究了下,效果是出来了,但是感觉不尽 ...
- Java static 静态代码块执行分析
假设有这样一个类: public class Utils { static { Log.i("static","isLoad!"); } public stat ...
- windows下编译chromium浏览器的15个流程整理
编译chromium 系统为windows, 国内在windows上编译chromium的资料比较少, 我这篇文章只能作为参考, 记录我遇到的一些问题,因为chromium团队也会修改了代码,或者编译 ...
- C#------判断btye[]是否为空
public byte[] PhotoByte; //= new byte[byte.MaxValue]; if(PhotoByte == null) { MessageBox.Show(" ...