【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 }
View Code

 

转载于:https://www.cnblogs.com/Lukaluka/p/5215891.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值