您的位置:首页 > 其它

BZOJ3173 [Tjoi2013]最长上升子序列

2015-01-30 23:09 387 查看
可以称为,模拟题、、、

我们发现,由于是从小到大插入的,所以后插入的数不会影响先插入的数的ans

于是只要对最后的序列求一次LIS即可。

问题就集中在如何求最后的序列:

方法一:treap无脑模拟插入操作

就当是treap的练手吧。。。结果RE了一版,后来突然一拍脑袋发现。。bz上不让调用time()函数。。。各种蛋疼

/**************************************************************
Problem: 3173
User: rausen
Language: C++
Result: Accepted
Time:248 ms
Memory:3540 kb
****************************************************************/

#include <cstdio>
#include <cstring>
#include <algorithm>

#define lowbit(x) (x & -x)
using namespace std;
const int N = 100005;
const int inf = 1e9;
const int Maxlen = N * 8;

int n, len;
int a
, ans
, mn
;
int bit
, b
;
char buf[Maxlen], *c = buf;
int Len;

inline int read() {
int x = 0;
while (*c < '0' || '9' < *c) ++c;
while ('0' <= *c && *c <= '9')
x = x * 10 + *c - '0', ++c;
return x;
}

void print(int x) {
if (x >= 10) print(x / 10);
putchar(x % 10 + '0');
}

inline int get_kth(int k) {
int res = 0, cnt = 0, i;
for (i = 20; ~i; --i) {
res += 1 << i;
if (res >= n || cnt + bit[res] >= k) res -= 1 << i;
else cnt += bit[res];
}
return res + 1;
}

inline void bit_del(int x) {
while (x <= n)
--bit[x], x += lowbit(x);
}

int main() {
Len = fread(c, 1, Maxlen, stdin);
buf[Len] = '\0';
int i, t, w, mx;
n = read();
for (i = 1; i <= n; ++i) {
b[i] = read(), ++bit[i];
if (i + lowbit(i) <= n)
bit[i + lowbit(i)] += bit[i];
}
for (i = n; i; --i) {
a[w = get_kth(b[i] + 1)] = i;
bit_del(w);
}
memset(mn, 127, sizeof(mn));
for (mn[0] = -inf, i = 1; i <= n; ++i) {
t = upper_bound(mn, mn + len + 1, a[i]) - mn;
if (mn[t - 1] <= a[i]) {
mn[t] = min(mn[t], a[i]);
ans[a[i]] = t;
len = max(t, len);
}
}
for (i = 1, mx = 0; i <= n; ++i) {
if (ans[i] > mx) mx = ans[i];
print(mx);
putchar('\n');
}
return 0;
}


View Code
(p.s. 在我的各种读入/输出/常数优化后,终于成为rank.1 yeah!)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: