wenbao与树状数组(BIT)

 经典入门题,敌兵布阵

 http://acm.hdu.edu.cn/showproblem.php?pid=1166

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 using namespace std;
 5 
 6 int n,aa[50005],cc[50005];
 7 
 8 int lowbit(int x){
 9     return x&(-x);
10 }
11 
12 void add(int x,int y){
13     while(x<=n){
14         cc[x]+=y;
15         x+=lowbit(x);
16     }
17 }
18 
19 int sum(int x){
20     int s=0;
21     while(x>0){
22         s+=cc[x];
23         x-=lowbit(x);
24     }
25     return s;
26 }
27 
28 int main(){
29     int t,countn=1;
30     char str[20];
31     scanf("%d",&t);
32     while(t--){
33         memset(aa,0,sizeof(aa));
34         memset(cc,0,sizeof(cc));
35         scanf("%d",&n);
36         for(int i=1;i<=n;i++){
37             scanf("%d",&aa[i]);
38             add(i,aa[i]);
39         }
40         printf("Case %d:
",countn);
41         while(~scanf("%s",str)){
42             if(str[0]=='E')
43                 break;
44             if(str[0]=='A'){
45                 int a,b;
46                 scanf("%d%d",&a,&b);
47                 add(a,b);
48             }
49             if(str[0]=='Q'){
50                 int a,b;
51                 scanf("%d%d",&a,&b);
52                 printf("%d
",sum(b)-sum(a-1));
53             }
54             if(str[0]=='S'){
55                 int a,b;
56                 scanf("%d%d",&a,&b);
57                 add(a,-b);
58             }
59         }
60         countn++;
61     }
62     return 0;
63 }

 -----------------------------------------------------------------------------------------

http://acm.hdu.edu.cn/showproblem.php?pid=4417

给定n个高度,有m个询问LR之间小于等于H的个数

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <string.h>
 4 using namespace std;
 5 #define bt(x) x&(-x)
 6 const int maxn = 1e5+10;
 7 int n, m, a[maxn], sum[maxn];
 8 struct Node{
 9     int x, y;
10     bool friend operator < (Node a, Node b){
11         return a.x < b.x;
12     }
13 }T[maxn];
14 struct Node2{
15     int l, r, x, y;
16     bool friend operator < (Node2 a, Node2 b){
17         return a.x < b.x;
18     }
19 }TT[maxn];
20 void ad(int x, int xx){
21     while(x <= n){
22         a[x] += xx;
23         x += bt(x);
24     }
25 }
26 int q(int x){
27     int sum = 0;
28     while(x){
29         sum += a[x];
30         x -= bt(x);
31     }
32     return sum;
33 }
34 int main(){
35     int t;
36     scanf("%d", &t);
37     for(int tt = 1; tt <= t; ++tt){
38         scanf("%d%d", &n, &m);
39         a[0] = 0;
40         for(int i = 1; i <= n; ++i){
41             a[i] = 0;
42             scanf("%d", &T[i].x);
43             T[i].y = i;
44         }
45         sort(T+1, T+n+1);
46         for(int i = 1; i <= m; ++i){
47             scanf("%d%d%d", &TT[i].l, &TT[i].r, &TT[i].x);
48             TT[i].y = i;
49         }
50         sort(TT+1, TT+m+1);
51         int num = 1;
52         printf("Case %d:
", tt);
53         for(int i = 1; i <= m; ++i){
54             int xx = TT[i].x;
55             while(num <= n && xx >= T[num].x){
56                 int xxx = T[num].y; 
57                 ad(xxx, 1);
58                 num ++;
59             }
60             sum[TT[i].y] = q(TT[i].r+1) - q(TT[i].l);
61         }
62         for(int i = 1; i <= m; ++i){
63             printf("%d
", sum[i]);
64         }
65     }
66     return 0;
67 }

 -----------------------------------------------------------------------------------------

 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=26&page=show_problem&problem=2330

一条街上住着n个乒乓球爱好者,有不同的能力值,每场比赛需要3个人(两名选手一名裁判)要求裁判住在选手中间并且能力值在两名选手中间,问一共可以组织多少种比赛

 1 #include <iostream>
 2 #include <string.h>
 3 using namespace std;
 4 #define ll long long
 5 #define bt(x) x&(-x)
 6 const int maxn = 1e5+10;;
 7 int t, n, a[maxn], b[maxn], c[maxn], d[maxn];
 8 void add(int x, int y){
 9     while(x < maxn){
10         d[x] += y;
11         x += bt(x);
12     }
13 }
14 int q(int x){
15     int sum = 0;
16     while(x){
17         sum += d[x];
18         x -= bt(x);
19     }
20     return sum;
21 }
22 int main(){
23     scanf("%d", &t);
24     while(t--){
25         scanf("%d", &n);
26         memset(d, 0, sizeof(int)*maxn);
27         for(int i = 1; i <= n; ++i){
28             scanf("%d", &a[i]);
29             add(a[i], 1);
30             b[i] = q(a[i]-1);
31         }
32         memset(d, 0, sizeof(int)*maxn);
33         for(int i = n; i >= 1; --i){
34             add(a[i], 1);
35             c[i] = q(a[i]-1);
36         }
37         ll sum = 0;
38         for(int i = 1; i <= n; ++i){
39             sum = sum + (ll)b[i]*(n-i-c[i]) + (ll)c[i]*(i-b[i]-1);
40         }
41         printf("%lld
", sum);
42     }
43     return 0;
44 }

  -----------------------------------------------------------------------------------------

http://poj.org/problem?id=2828

神奇的BIT

find函数,利用二进制来快速求出第k大数,只需log复杂度

 1 #include <iostream>
 2 #include <string.h>
 3 using namespace std;
 4 #define bt(x) x&(-x)
 5 const int maxn = 200009;
 6 int n, a[maxn], b[maxn], sum[maxn], c[maxn];
 7 void add(int x, int y){
 8     while(x <= n){
 9         sum[x] += y;
10         x += bt(x);
11     }
12 }
13 int f(int x){
14     int xx = 0, yy = 0;
15     for(int i = 20; i >= 0; --i){
16         xx += 1<<i;
17         if(xx > n || yy + sum[xx] >= x){
18             xx -= 1<<i;
19         }else{
20             yy += sum[xx];
21         }
22     }
23     return xx+1;
24 }
25 int main(){
26     while(~scanf("%d", &n)){
27         memset(sum, 0, sizeof(int)*maxn);
28         for(int i = 1; i <= n; ++i){
29             scanf("%d%d", &a[i], &b[i]);
30             add(i, 1);
31         }
32         for(int i = n; i >= 1; --i){
33             int xx = f(a[i]+1);
34             c[xx] = b[i];
35             add(xx, -1);
36         }
37         for(int i = 1; i <= n; ++i){
38             printf("%d%c", c[i], i == n ? '
' : ' ');
39         }
40     }
41     return 0;
42 }

  -----------------------------------------------------------------------------------------

区间更新

 推荐博客http://www.cnblogs.com/lcf-2000/p/5866170.html

自从有了它之后。。什么?线段树是什么?

 1 #include <iostream>
 2 using namespace std;
 3 #define ll long long
 4 #define bt(x) x&-x
 5 const int maxn = 100009;
 6 int n, m, x, y;
 7 ll xx, c1[maxn], c2[maxn];
 8 void add(int x, ll y){
 9     for(int i = x; i <= n; i += bt(i)) c1[i] += y, c2[i] += x*y;
10 }
11 ll f(int x){
12     ll sum = 0;
13     for(int i = x; i; i -= bt(i)) sum += c1[i]*(x+1) - c2[i];
14     return sum;
15 }
16 int main(){
17     scanf("%d%d", &n, &m);
18     for(int i = 1; i <= n; ++i){
19         scanf("%lld", &xx);
20         add(i, xx), add(i+1, -xx);
21     }
22     char str[3];
23     for(int i = 0; i < m; ++i){
24         scanf("%s", str);
25         if(str[0] == 'Q'){
26             scanf("%d%d", &x, &y);
27             printf("%lld
", f(y)-f(x-1));
28         }else{
29             scanf("%d%d%lld", &x, &y, &xx);
30             add(x, xx), add(y+1, -xx);
31         }
32     }
33     return 0;
34 }

  -----------------------------------------------------------------------------------------

https://loj.ac/problem/524

如果没有X直接判断逆序对奇偶性,否则判断X个数的奇偶性(1要特判)

因为最后一个放的人肯定可以放成胜态

 1 #include <iostream>
 2 #include <map>
 3 #include <string.h>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 const int M = 1e9+5;
 8 const int maxn = 100009;
 9 char str[222];
10 int a[maxn], n, numx, numi = 1, b[maxn], m[maxn];
11 
12 void add(int x){
13     while(x <= numi){
14         m[x] += 1;
15         x += (x&-x);
16     }
17 }
18 
19 int f(int x){
20     int sum = 0;
21     while(x){
22         sum += m[x];
23         x -= (x&-x);
24     }
25     return sum;
26 }
27 
28 int q(){
29     int num = 0;
30     for(int i = 1; i < numi; ++i){
31         num += f(b[i]);
32         add(b[i]);
33     }
34     return num;
35 }
36 
37 int main(){
38     scanf("%d", &n);
39     for(int i = 0; i < n; ++i){
40         scanf("%s", str);
41         if(str[0] == 'X') numx ++;
42         else a[numi++] = atoi(str);
43     }
44     if(!numx){
45         for(int i = 1; i < numi; ++i) b[i] = i;
46         sort(b+1, b+numi, [](int x, int y){
47             return a[x] < a[y];
48         });
49         if(q()&1) printf("W
");
50         else printf("L
");
51         return 0;
52     }
53     if(n == 1){
54         return printf("L
"), 0;
55     }
56     if(numx&1) printf("W
");
57     else printf("L
");
58     return 0;
59 }

  -----------------------------------------------------------------------------------------

  -----------------------------------------------------------------------------------------

  -----------------------------------------------------------------------------------------

  -----------------------------------------------------------------------------------------

  -----------------------------------------------------------------------------------------

  -----------------------------------------------------------------------------------------

  -----------------------------------------------------------------------------------------

只有不断学习才能进步!

原文地址:https://www.cnblogs.com/wenbao/p/5694305.html