Description
给定一个序列,初始为空。现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置。每插入一个数字,我们都想知道此时最长上升子序列长度是多少?
Sample Input
3
0 0 2
Sample Output
1
1
2
这道题首先我们的思路是求出每个数放的位置,这个过程我们倒着插,是可以二分的。
然后再考虑求最长上升子序列,用树状数组维护全局最大值。。。
#include <cstdio>
#include <cstring>
using namespace std;
int _max(int x, int y) {return x > y ? x : y;}
int n, a[110000], s[110000];
int lowbit(int x) {return x & -x;}
void change1(int x, int c) {
for(int i = x; i <= n; i += lowbit(i)) s[i] += c;
}
void change2(int x, int c) {
for(int i = x; i <= n; i += lowbit(i)) s[i] = _max(s[i], c);
}
int getsum(int x) {
int sum = 0;
for(int i = x; i >= 1; i -= lowbit(i)) sum += s[i];
return sum;
}
int getmax(int x) {
int maxx = 0;
for(int i = x; i >= 1; i -= lowbit(i)) maxx = _max(maxx, s[i]);
return maxx;
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]), a[i]++;
for(int i = n; i >= 1; i--) {
int x = a[i];
int l = a[i], r = n;
while(l <= r) {
int mid = (l + r) / 2;
if(getsum(mid) <= mid - x) a[i] = mid, r = mid - 1;
else l = mid + 1;
}
change1(a[i], 1);
}
int ans = 0;
memset(s, 0, sizeof(s));
for(int i = 1; i <= n; i++) {
int s = getmax(a[i] - 1) + 1;
ans = _max(ans, s);
change2(a[i], s);
printf("%d\n", ans);
}
return 0;
}