【BZOJ3173】【Tjoi2013】最长上升子序列(树状数组)
传送门w:http://www.lydsy.com/JudgeOnline/problem.php?id=3173
QwQ这个题大多数做法都是Treap+Bit,然后窝看到了一个只用Bit的题解,感觉思路很巧妙啊:http://blog.csdn.net/d_william/article/details/9146757
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <iostream> 5 #define MaxN 111111 6 using namespace std; 7 int n; 8 struct Bit{ 9 int s[MaxN]; 10 int lowbit(int x) { return x&-x; } 11 12 void Reset() { memset(s, 0, sizeof(s)); } 13 14 void add(int x, int c){ 15 int i = x; 16 while (i <= n){ 17 s[i] += c; 18 i += lowbit(i); 19 } 20 } 21 22 void updata(int x, int c){ 23 int i = x; 24 while (i <= n){ 25 s[i] = max(s[i], c); 26 i += lowbit(i); 27 } 28 } 29 30 int query(int x){ 31 int ret = 0, i = x; 32 while (i > 0){ 33 ret = max(ret, s[i]); 34 i -= lowbit(i); 35 } 36 return ret; 37 } 38 39 int queryS(int x){ 40 int ret = 0, i = x; 41 while (i > 0){ 42 ret += s[i]; 43 i -= lowbit(i); 44 } 45 return ret; 46 } 47 48 }A, B; 49 int pos[MaxN], orz[MaxN], ans[MaxN]; 50 51 int getpos(int x){ 52 int l = 0, r = n+1, mid; 53 while (l + 1 < r){ 54 mid = (l+r) >> 1; 55 int t = A.queryS(mid); 56 if (t < x) l = mid; 57 else r = mid; 58 } 59 return r; 60 } 61 62 int main(){ 63 scanf("%d", &n); 64 A.Reset(); B.Reset(); 65 for (int i = 1; i <= n; i++) { scanf("%d", &pos[i]); pos[i]++; A.add(i, 1); } 66 for (int i = n; i; i--){ 67 int p = getpos(pos[i]); 68 orz[i] = p; 69 A.add(p, -1); 70 } 71 for (int i = 1; i <= n; i++){ 72 int t = B.query(orz[i]-1)+1; 73 ans[i] = max(ans[i-1], t); 74 B.updata(orz[i], t); 75 } 76 for (int i = 1; i <= n; i++) printf("%d\n", ans[i]); 77 return 0; 78 }