可以称为,模拟题、、、
我们发现,由于是从小到大插入的,所以后插入的数不会影响先插入的数的ans
于是只要对最后的序列求一次LIS即可。
问题就集中在如何求最后的序列:
方法一:treap无脑模拟插入操作
就当是treap的练手吧。。。结果RE了一版,后来突然一拍脑袋发现。。bz上不让调用time()函数。。。各种蛋疼
1 /************************************************************** 2 Problem: 3173 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:660 ms 7 Memory:3936 kb 8 ****************************************************************/ 9 10 #include <cstdlib> 11 #include <cstdio> 12 #include <cstring> 13 #include <algorithm> 14 15 using namespace std; 16 const int N = 100005; 17 const int inf = 1e9; 18 19 struct treap_node { 20 treap_node *son[2]; 21 int pri, sz, v; 22 } *null, *root, mempool[N], *cnt_treap = mempool; 23 24 int n, cnt, len; 25 int a[N], ans[N], mn[N]; 26 27 int read() { 28 int x = 0; 29 char ch = getchar(); 30 while (ch < '0' || '9' < ch) 31 ch = getchar(); 32 while ('0' <= ch && ch <= '9') 33 (x *= 10) += ch - '0', ch = getchar(); 34 return x; 35 } 36 37 #define Ls (p -> son[0]) 38 #define Rs (p -> son[1]) 39 #define Pri (p -> pri) 40 #define Sz (p -> sz) 41 #define V (p -> v) 42 inline void treap_update(treap_node *p) { 43 Sz = Ls -> sz + Rs -> sz + 1; 44 } 45 46 void treap_rotate(treap_node *&p, int ch) { 47 treap_node *tmp = p -> son[ch]; 48 p -> son[ch] = tmp -> son[!ch]; 49 tmp -> son[!ch] = p; 50 treap_update(p), treap_update(tmp); 51 p = tmp; 52 } 53 54 void treap_insert(treap_node *&p, int rank) { 55 if (p == null) { 56 p = ++cnt_treap, Ls = Rs = null; 57 Pri = rand(), Sz = 1, V = cnt; 58 return; 59 } 60 ++Sz; 61 if (Ls -> sz < rank) { 62 treap_insert(Rs, rank - Ls -> sz - 1); 63 if (Rs -> pri > Pri) treap_rotate(p, 1); 64 } else { 65 treap_insert(Ls, rank); 66 if (Ls -> pri > Pri) treap_rotate(p, 0); 67 } 68 } 69 70 void get_seq(treap_node *p) { 71 if (p == null) return; 72 get_seq(Ls); 73 a[++cnt] = V; 74 get_seq(Rs); 75 } 76 #undef Ls 77 #undef Rs 78 #undef Pri 79 #undef Sz 80 #undef Num 81 82 int main() { 83 int i, t; 84 n = read(); 85 null = ++cnt_treap; 86 null -> son[0] = null -> son[1] = null; 87 null -> pri = null -> sz = null -> v = 0; 88 root = null; 89 for (cnt = 1; cnt <= n; ++cnt) 90 treap_insert(root, read()); 91 cnt = 0; 92 get_seq(root); 93 memset(mn, 127, sizeof(mn)); 94 for (mn[0] = -inf, i = 1; i <= n; ++i) { 95 t = upper_bound(mn, mn + len + 1, a[i]) - mn; 96 if (mn[t - 1] <= a[i]) { 97 mn[t] = min(mn[t], a[i]); 98 ans[a[i]] = t; 99 len = max(t, len); 100 } 101 } 102 for (i = 1; i <= n; ++i) 103 printf("%d\n", ans[i] = max(ans[i], ans[i - 1])); 104 return 0; 105 }
方法二:倒过来做,从最后开始一个个删,用树状数组维护,求序列的前缀第k大
BIT的这种应用方式也是蛮神的。。。
1 /************************************************************** 2 Problem: 3173 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:248 ms 7 Memory:3540 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <cstring> 12 #include <algorithm> 13 14 #define lowbit(x) (x & -x) 15 using namespace std; 16 const int N = 100005; 17 const int inf = 1e9; 18 const int Maxlen = N * 8; 19 20 int n, len; 21 int a[N], ans[N], mn[N]; 22 int bit[N], b[N]; 23 char buf[Maxlen], *c = buf; 24 int Len; 25 26 inline int read() { 27 int x = 0; 28 while (*c < '0' || '9' < *c) ++c; 29 while ('0' <= *c && *c <= '9') 30 x = x * 10 + *c - '0', ++c; 31 return x; 32 } 33 34 void print(int x) { 35 if (x >= 10) print(x / 10); 36 putchar(x % 10 + '0'); 37 } 38 39 inline int get_kth(int k) { 40 int res = 0, cnt = 0, i; 41 for (i = 20; ~i; --i) { 42 res += 1 << i; 43 if (res >= n || cnt + bit[res] >= k) res -= 1 << i; 44 else cnt += bit[res]; 45 } 46 return res + 1; 47 } 48 49 inline void bit_del(int x) { 50 while (x <= n) 51 --bit[x], x += lowbit(x); 52 } 53 54 int main() { 55 Len = fread(c, 1, Maxlen, stdin); 56 buf[Len] = '\0'; 57 int i, t, w, mx; 58 n = read(); 59 for (i = 1; i <= n; ++i) { 60 b[i] = read(), ++bit[i]; 61 if (i + lowbit(i) <= n) 62 bit[i + lowbit(i)] += bit[i]; 63 } 64 for (i = n; i; --i) { 65 a[w = get_kth(b[i] + 1)] = i; 66 bit_del(w); 67 } 68 memset(mn, 127, sizeof(mn)); 69 for (mn[0] = -inf, i = 1; i <= n; ++i) { 70 t = upper_bound(mn, mn + len + 1, a[i]) - mn; 71 if (mn[t - 1] <= a[i]) { 72 mn[t] = min(mn[t], a[i]); 73 ans[a[i]] = t; 74 len = max(t, len); 75 } 76 } 77 for (i = 1, mx = 0; i <= n; ++i) { 78 if (ans[i] > mx) mx = ans[i]; 79 print(mx); 80 putchar('\n'); 81 } 82 return 0; 83 }
(p.s. 在我的各种读入/输出/常数优化后,终于成为rank.1 yeah!)
By Xs酱~ 转载请说明
博客地址:http://www.cnblogs.com/rausen