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

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

--------------------------------------------------------------------

#include<bits/stdc++.h>

#define rep(i, n) for(int i = 0; i < n; ++i)

#define clr(x, c) memset(x, c, sizeof(x))

#define foreach(i, x) for(__typeof(x.begin()) i = x.begin(); i != x.end(); i++)

using namespace std;

const int maxn = 100009;

struct Node {

Node *ch[2], *p;

int s, v;

inline void upd() {

s = ch[0]->s + ch[1]->s + 1;

}

inline void setc(Node* t, int d) {

ch[d] = t;

t->p =this;

}

inline bool d() {

return this == p->ch[1];

}

} pool[maxn], *pt = pool, *root, *null;

Node* newNode(int _ = 0) {

pt->v = _; pt->s = 1;

pt->ch[0] = pt->ch[1] = pt->p = null;

return pt++;

}

void rot(Node* t) {

Node* p = t->p;

int d = t->d();

p->p->setc(t, p->d());

p->setc(t->ch[d ^ 1], d);

t->setc(p, d ^ 1);

p->upd();

if(p == root) root = t;

}

void splay(Node* t, Node* f = null) {

while(t->p != f) {

if(t->p->p != f)

t->d() != t->p->d() ? rot(t) : rot(t->p);

rot(t);

}

t->upd();

}

Node* select(int k) {

for(Node* t = root; ;) {

int s = t->ch[0]->s;

if(k == s) return t;

if(k > s)

k -= s + 1, t = t->ch[1];

else

t = t->ch[0];

}

}

void init() {

null = newNode();

null->ch[0] = null->ch[1] = null->p = null;

null->s = 0;

root = newNode(maxn);

root->setc(newNode(-maxn), 0);

root->upd();

}

int seq[maxn], N = 0, g[maxn], dp[maxn];

void dfs(Node* t) {

if(t == null) return;

dfs(t->ch[0]);

if(t->v != maxn && t->v != -maxn) seq[N++] = t->v;

dfs(t->ch[1]);

}

int main() {

freopen("test.in", "r", stdin);

init();

int n;

cin >> n;

rep(i, n) {

int v;

scanf("%d", &v);

Node *L = select(v), *R = select(v + 1);

splay(L); splay(R, L);

R->setc(newNode(i), 0);

R->upd(); L->upd();

g[i] = maxn;

}

dfs(root);

rep(i, n) {

int p = lower_bound(g, g + n, seq[i]) - g;

dp[seq[i]] = p + 1;

g[p] = seq[i];

}

int ans = 0;

rep(i, n) {

ans = max(ans, dp[i]);

printf("%d\n", ans);

}

return 0;

}

--------------------------------------------------------------------

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

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 806  Solved: 432
[Submit][Status][Discuss]

Description

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

Input

第一行一个整数N,表示我们要将1到N插入序列中,接下是N个数字,第k个数字Xk,表示我们将k插入到位置Xk(0<=Xk<=k-1,1<=k<=N)

Output

N行,第i行表示i插入Xi位置后序列的最长上升子序列的长度是多少。

Sample Input

3
0 0 2

Sample Output

1
1
2

HINT

100%的数据 n<=100000

Source

时间: 2024-10-03 09:14:56

BZOJ 3173: [Tjoi2013]最长上升子序列( BST + LIS )的相关文章

BZOJ 3173 [Tjoi2013]最长上升子序列 Treap+LIS

题意:链接 方法: Treap+LIS 解析: 刚看到题还蒙了一会,无从下手啊- -! 后来寻思找找规律. 画画样例以及瞎编了两组数据之后发现点问题- 答案递增? 然后才反应过来- -,当我们从小到大插入的时候,插入后的情况是不影响插入前的. 所以这样的话我们可以把整个序列先弄出来? 之后求一个LIS,这时候对于每一个数来说,他都有个LIS值,当然这个可能不是他插入之后的最优解,因为之前的值可能比他插入之后还要大. 所以我们再需要扫一下数组,更新下答案即可. 至于第一部分找序列,用treap实现

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

3173: [Tjoi2013]最长上升子序列 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1613  Solved: 839[Submit][Status][Discuss] Description 给定一个序列,初始为空.现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置.每插入一个数字,我们都想知道此时最长上升子序列长度是多少? Input 第一行一个整数N,表示我们要将1到N插入序列中,接下是N个数字,第k个数字Xk

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

3173: [Tjoi2013]最长上升子序列 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1524  Solved: 797[Submit][Status][Discuss] Description 给定一个序列,初始为空.现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置.每插入一个数字,我们都想知道此时最长上升子序列长度是多少? Input 第一行一个整数N,表示我们要将1到N插入序列中,接下是N个数字,第k个数字Xk

bzoj 3173: [Tjoi2013]最长上升子序列(splay)

3173: [Tjoi2013]最长上升子序列 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 1315  Solved: 682 [Submit][Status][Discuss] Description 给定一个序列,初始为空.现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置.每插入一个数字,我们都想知道此时最长上升子序列长度是多少? Input 第一行一个整数N,表示我们要将1到N插入序列中,接下是N个数字,第k个数字

BZOJ 3173 [Tjoi2013] 最长上升子序列 解题报告

这个题感觉比较简单,但却比较容易想残.. 我不会用树状数组求这个原排列,于是我只好用线段树...毕竟 Gromah 果弱马. 我们可以直接依次求出原排列的元素,每次找到最小并且最靠右的那个元素,假设这是第 $i$ 次找的,那么这就是原排列的第 $i$ 项,然后我们就把这个元素删去(变成很大的数),再把这个数以左的数都加 1,进行下一轮. 然后就是裸的最长上升子序列啦~~~ 时间复杂度 $O(n\log n)$,空间复杂度 $O(n)$. 1 #include <cstdio> 2 #inclu

BZOJ 3173 Tjoi2013 最长上升子序列 Treap+树状数组

题目大意:给定一个序列,依次将1~n插入,问每次插入之后序列的LIS长度是多少 由于是从小到大插入,因此插入一个数之后显然是不影响之前的答案的 因此我们不妨先用平衡树搞出插入之后的序列,再求一遍LIS即可 注意最后每个点还要对前面的取一下max 因为插入后LIS可能还是之前的序列 蒟蒻的我到底还是把平衡树写挂了... #include <cstdio> #include <cstring> #include <iostream> #include <algorit

P4309 [TJOI2013]最长上升子序列

题目 P4309 [TJOI2013]最长上升子序列 做法 最长上升序列的求法肯定是烂大街了 水题是肯定的,确定出序列的位置然后套个树状数组就好了(强制在线的话改成线段树维护前缀最值也行) 所以说这题其实难点在与怎么让代码简洁,见识到一个新的\(STL\):\(rope\) My complete code #include<bits/stdc++.h> #include<ext/rope> using namespace std; typedef int LL; const LL

最长公共子序列(LCS)、最长递增子序列(LIS)、最长递增公共子序列(LICS)

最长公共子序列(LCS) [问题] 求两字符序列的最长公共字符子序列 问题描述:字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0,y1,…,yk-1”是X的子序列,存在X的一个严格递增下标序列<i0,i1,…,ik-1>,使得对所有的j=0,1,…,k-1,有xij=yj.例如,X=“ABCBDAB”,Y=“BCDB”是X的一个子序列. 考虑最长公共子序列问题如何分解成

poj 3903 &amp; poj 2533 最长上升子序列(LIS)

最长上升子序列. 做这道题之前先做了2533,再看这道题,感觉两道题就一模一样,于是用2533的代码直接交, TLE了: 回头一看,数据范围.2533 N:0~1000:3903 N :1~100000. 原因终归于算法时间复杂度. 也借这道题学习了nlgn的最长上升子序列.(学习链接:http://blog.csdn.net/dangwenliang/article/details/5728363) 下面简单介绍n^2 和 nlgn 的两种算法. n^2: 主要思想:DP: 假设A1,A2..