Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1361 Accepted Submission(s): 492
Problem Description
There is a sequence firstly empty. We begin to add number from 1 to N to the sequence, and every time we just add a single number to the sequence at a specific position. Now, we want to know length of the LIS (Longest Increasing Subsequence) after every time's add.
Input
An integer T (T <= 10), indicating there are T test cases.
For every test case, an integer N (1 <= N <= 100000) comes first, then there are N numbers, the k-th number Xk means that we add number k at position Xk (0 <= Xk <= k-1).See hint for more details.
For every test case, an integer N (1 <= N <= 100000) comes first, then there are N numbers, the k-th number Xk means that we add number k at position Xk (0 <= Xk <= k-1).See hint for more details.
Output
For the k-th test case, first output "Case #k:" in a separate line, then followed N lines indicating the answer. Output a blank line after every test case.
Sample Input
1
3
0 0 2
Sample Output
Case #1:
1
1
2
Hint
In the sample, we add three numbers to the sequence, and form three sequences.
a. 1
b. 2 1
c. 2 1 3
Author
standy
Source
思路:由于是从大到小插值的,那么我们只需要知道最终的序列,再对其求一遍LIS即可。可以用线段树求最终的序列,从后往前考虑,一开始有n个空位,对于每个数的插入位置a[i],其应该放在从左往右的第a[i]个空格,放完数后该空格被占用。该问题相当于给出n个数,多次操作,找出第k1个数后,将该数删去,继续找第k2个数。。。
#include <bits/stdc++.h> using namespace std; const int N = 100000 + 5; #define lson rt << 1, l, m #define rson rt <<1|1, m + 1, r int num[N << 2]; int a[N], pos[N], ans[N], res[N], n; void build(int rt, int l, int r) { num[rt] = r - l + 1; if(l == r) return ; int m = (l + r) >> 1; build(lson); build(rson); } void update(int rt, int l, int r, int k, int v) { if(l == r) { pos[l] = v; num[rt] = 0; return; } int m = (l + r) >> 1; if(k > num[rt << 1]) update(rson, k - num[rt << 1], v); else update(lson, k, v); num[rt] = num[rt << 1] + num[rt << 1|1]; } int LIS[N], len; void solve() { len = 1; LIS[0] = 0; for(int i = 1; i <= n; ++i) { int p = upper_bound(LIS, LIS + len, pos[i]) - LIS - 1; LIS[p + 1] = pos[i]; ans[i] = p + 1; if(p + 1 == len) len++; } } int main() { // freopen("in.txt", "r", stdin); int _, cas = 1; scanf("%d", &_); while(_ --) { scanf("%d", &n); build(1, 1, n); // puts("-----BUG-----"); for(int i = 1; i <= n; ++i) { scanf("%d", a + i); a[i]++; } for(int i = n; i >= 1; --i) update(1, 1, n, a[i], i); solve(); for(int i = 1; i <= n; ++i) res[ pos[i] ] = ans[i]; for(int i = 2; i <= n; ++i) res[i] = max(res[i], res[i - 1]); printf("Case #%d: ", cas++); for(int i = 1; i <= n; ++i) printf("%d ", res[i]); puts(""); } }