树状数组有一个很牛逼的名字,叫二叉检索树,其中用O(log n)的算法可以统计前n项的和,成就了该算法的优美。

    全世界都有这个标程,贴出来看看

代码
1 const int maxn = ;
2  int c[maxn];
3
4  int lowbit(int x) { return x & (-x); }
5
6  void update(int x , int delta)
7 {
8 while(x < maxn) {
9 c[x] += delta;
10 x += lowbit(x);
11 }
12 }
13
14 int sum(int x)
15 {
16 int S = 0;
17 while(x > 0) {
18 S += c[x];
19 x -= lowbit(x);
20 }
21 return S;
22 }
23
24 //二分逼近寻找第K大,返回其下标
25 //若寻找第K小:
26 //1.则可以将update函数delta的值换成相反数,再找第K大
27 //2.第K小为第K大的N - K项
28
29 int find(int k)
30 {
31 int mod = 0, ans = 0;
32 for(int i = 18; i >= 0; i --) {
33 ans += (1 << i);
34 if(mod + c[ans] >= k)
35 ans -= (1 << i);
36 else
37 mod += c[ans];
38 }
39 return ans + 1;
40 }

    POJ2299 Ultra-QuickSort

    http://acm.pku.edu.cn/JudgeOnline/problem?id=2299

    先离散化,然后逐个插入,每次插入统计前n项有多少位比他小的(不包括自己),于是最终答案为(n * (n - 1)) / 2 - s;

代码
1 #include <iostream>
2 #include <algorithm>
3 using namespace std;
4
5 typedef __int64 LL;
6
7 const int maxn = 500005;
8
9 LL a[maxn], b[maxn], c[maxn], t[maxn];
10 LL n, len;
11
12 int search(LL x)
13 {
14 int l = 0 , r = len;
15 while(l <= r)
16 {
17 //cout << l << ' ' << r << endl;
18 int m = (l + r) >> 1;
19 if(b[ m ] < x)
20 l = m + 1;
21 else if(b[ m ] > x)
22 r = m - 1;
23 else return m;
24 }
25 }
26
27 int lowbit(int x) { return x & (-x); }
28
29 void modify(int x , int delta) {
30 while(x < maxn) {
31 c[x] += delta;
32 x += lowbit(x);
33 }
34 }
35
36 LL sum(int x) {
37 LL S = 0;
38 while(x > 0) {
39 S += c[x];
40 x -= lowbit(x);
41 }
42 return S;
43 }
44
45 int main()
46 {
47 while(~scanf("%d", &n), n)
48 {
49 memset(c , 0 , sizeof(c));
50 len = 1;
51 for(int i=0; i < n; i++)
52 {
53 scanf("%I64d", &a[i]);
54 t[i] = a[i];
55 }
56 sort(t , t + n);
57 b[0] = t[0];
58 for(int i=1; i < n; i++)
59 {
60 if(t[i] != b[len - 1])
61 b[len ++] = t[i];
62 }
63 LL s = 0, ans = (n * (n - 1)) >> 1;
64 for(int i=0; i < n; i++)
65 {
66 int tmp = search(a[i]) + 1;
67 s += sum(tmp - 1);
68 modify(tmp , 1);
69
70 }
71 printf("%I64d\n", ans - s);
72 }
73 return 0;
74 }
75

    POJ2761 Feed the dogs

    http://acm.pku.edu.cn/JudgeOnline/problem?id=2761

    离散化,然后找第K大,速度比我的SBT快

代码
1 #include <iostream>
2 #include <algorithm>
3 using namespace std;
4
5 const int maxn = 500005;
6 int n, m, len;
7 int ans[maxn], bin[maxn], b[maxn], c[maxn], val[maxn];
8 struct NODE { int u, v, k, id; } A[maxn];
9
10 void init()
11 {
12 len = 1;
13 b[0] = bin[0];
14 for(int i=1; i < n; i++)
15 {
16 if(bin[i] != b[len - 1])
17 b[len ++] = bin[i];
18 }
19 }
20
21 int search(int x)
22 {
23 int l = 0 , r = len;
24 while(l <= r)
25 {

27 int m = (l + r) >> 1;
28 if(b[ m ] < x)
29 l = m + 1;
30 else if(b[ m ] > x)
31 r = m - 1;
32 else return m + 1;
33 }
34 }
35
36 int lowbit(int x) { return x & (-x); }
37
38 void update(int x , int delta) {
39 while(x < maxn) {
40 c[x] += delta;
41 x += lowbit(x);
42 }
43 }
44
45 int sum(int x) {
46 int S = 0;
47 while(x > 0) {
48 S += c[x];
49 x -= lowbit(x);
50 }
51 return S;
52 }
53
54 int find(int k)
55 {
56 int cnt = 0, ans = 0;
57 for(int i = 18; i >= 0; i --)
58 {
59 ans += (1 << i);
60 if(cnt + c[ans] >= k)
61 ans -= (1 << i);
62 else cnt += c[ans];
63 }
64 return ans + 1;
65 }
66
67 bool operator < (const NODE x, const NODE y)
68 {
69 if(x.u == y.u)
70 return x.v < y.v;
71 return x.u < y.u;
72 }
73
74 int main()
75 {
76 scanf("%d %d", &n, &m);
77 int root = 0;
78 for(int i=1; i <= n; i++) {
79 scanf("%d", &val[i]);
80 bin[i - 1] = val[i];
81 }
82
83 sort(bin , bin + n);
84 init();
85
86 for(int i=0; i < m; i++) {
87 scanf("%d %d %d", &A[i].u, &A[i].v, &A[i].k);
88 if(A[i].u > A[i].v)
89 swap(A[i].u , A[i].v);
90 A[i].id = i;
91 }
92
93 sort(A, A + m);
94
95 int st = A[0].u, et = A[0].v;
96 for(int j=st; j <= et; j++)
97 update(search(val[j]) , 1);
98 ans[ A[0].id ] = find(A[0].k);
99
100 for(int i=1; i < m; i++) {
101
102 if(A[i].v <= A[i - 1].v) {
103 for(int j=A[i - 1].u; j < A[i].u; j++)
104 update(search(val[j]) , -1);
105 for(int j=A[i].v + 1; j <= A[i - 1].v; j++)
106 update(search(val[j]) , -1);
107 st = 1; et = 0;
108 } else if(A[i].u <= A[i - 1].v && A[i].v >= A[i - 1].v) {
109 for(int j=A[i - 1].u; j < A[i].u; j++)
110 update(search(val[j]) , -1);
111 st = A[i - 1].v + 1; et = A[i].v;
112 } else {
113 for(int j=A[i - 1].u; j <= A[i - 1].v; j++)
114 update(search(val[j]) , -1);
115 st = A[i].u; et = A[i].v;
116 }
117
118 for(int j=st; j <= et; j++)
119 update(search(val[j]) , 1);
120 ans[ A[i].id ] = find(A[i].k);
121
122 }
123
124 for(int i=0; i < m; i++)
125 printf("%d\n", b[ ans[i] - 1 ]);
126 return 0;
127 }
128
129

 

posted on 2010-05-21 20:33  xIao.wU 思维磁场  阅读(219)  评论(0编辑  收藏  举报