[树状数组]求逆序对

树状数组基本讲解:

树状数组的用途就是求前缀和,他的本质跟线段树相似,就是一个空间换时间。

主要采用lowbit,通过二进制从而划分区间。

增加的时候,从下往上依次加lowbit

查询的时候,从上往下减去lowbit。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cmath>
 6 #include <algorithm>
 7 #include <queue>
 8 #include <string>
 9 #include <vector>
10 #define For(a,b) for(int a=0;a<b;a++)
11 #define mem(a,b) memset(a,b,sizeof(a))
12 #define _mem(a,b) memset(a,0,(b+1)<<2)
13 #define lowbit(a) ((a)&-(a))
14 using namespace std;
15 typedef long long ll;
16 const int maxn =  5*1e4+5;
17 const int INF = 0x3f3f3f3f;
18 int c[maxn];
19 void update(int x,int y,int n){
20     for(int i=x;i<=n;i+=lowbit(i))
21         c[i] += y;
22 }
23 int getsum(int x){
24     int ans = 0;
25     for(int i=x;i;i-=lowbit(i))
26         ans += c[i];
27     return ans;
28 }
29 int main()
30 {
31     int t;
32     int n;
33     int x,y,z;
34     string s;
35     cin >> t ;
36     for(int j=1;j<=t;j++){
37         scanf("%d",&n);
38         _mem(c,n);      //初始化数组中前n+1个数为0
39         for(int i=1;i<=n;i++){
40             scanf("%d",&z);
41             update(i,z,n);
42         }
43         cout <<"Case "<<j<<":"<<endl;
44         while(1){
45             cin >> s;
46             if(s[0] == 'E')
47                 break;
48             scanf("%d%d",&x,&y);
49             if(s[0] == 'Q')
50                 cout << getsum(y)-getsum(x-1)<<endl;
51             else if(s[0] == 'A')
52                 update(x,y,n);
53             else
54                 update(x,-y,n);
55         }
56     }
57     return 0;
58 }
View Code

求逆序对!

ci 的意思是在前lowbit 中元素的个数。

然后往前i个中的sum就是小于等于这个i的个数

这个数的位置-小于等于这个i的个数 就是前面大于这个数的个数

小于等于这个数的个数肯定比 这个数的位置要小。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<string>
 5 #include<cstring>
 6 #include<queue>
 7 #include<map>
 8 #include<set>
 9 #include<algorithm>
10 using namespace std;
11 typedef long long ll;
12 const int N=1000+10;
13 int c[N],n,aa;
14 int lowbit(int x)
15 {
16     return x&-x;
17 }
18 void insert(int i,int x)
19 {
20     while(i<=n)
21     {
22         c[i]+=x;
23         i+=lowbit(i);
24     }
25 }
26 int getsum(int i)
27 {
28     int sum=0;
29     while(i>0)
30     {
31         sum+=c[i];
32         i-=lowbit(i);
33     }
34     return sum;
35 }
36 int main()
37 {
38     while(scanf("%d",&n)!=EOF)
39     {
40     int ans=0;
41     memset(c,0,sizeof(c));
42     for(int i=1;i<=n;i++)
43     {
44         scanf("%d",&aa);
45         insert(aa,1);
46         ans+=i-getsum(aa);
47     }
48     printf("%d\n",ans);
49     }
50     return 0;
51 }
View Code

挖个坑下回把归并和快排的求逆序对放下来。

 

F - Cube

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <algorithm>
 6 #include <set>
 7 #include <map>
 8 #include <vector>
 9 #include <cctype>
10 #include <sstream>
11 using namespace std;
12 typedef long long ll;
13 const int inf=0x7fffffff;
14 const int N=110;
15 const int M=500000+10;
16 int a[N][N][N],c[N][N][N];
17 int n,m;
18 int lowbit(int x)
19 {
20     return x&-x;
21 }
22 void insert(int x,int y,int z,int iii)
23 {
24     for(int i=x;i<=n;i+=lowbit(i))
25         for(int j=y;j<=n;j+=lowbit(j))
26             for(int k=z;k<=n;k+=lowbit(k))
27                 c[i][j][k]+=iii;
28 }
29 int getsum(int x,int y,int z)
30 {
31     int sum=0;
32     for(int i=x;i>0;i-=lowbit(i))
33         for(int j=y;j>0;j-=lowbit(j))
34             for(int k=z;k>0;k-=lowbit(k))
35                 sum+=c[i][j][k];
36     return sum;
37 }
38 int main()
39 {
40     while(scanf("%d %d",&n,&m)!=EOF)
41     {
42         memset(c,0,sizeof(c));
43     int ss,xx,yy,zz;
44     while(m--)
45     {
46         scanf("%d %d %d %d",&ss,&xx,&yy,&zz);
47         if(ss==1)
48         {
49             int xxx,yyy,zzz;
50             scanf("%d %d %d",&xxx,&yyy,&zzz);
51             xxx++;  yyy++;  zzz++;
52             insert(xx,yy,zz,1);
53             insert(xx,yy,zzz,1);
54             insert(xx,yyy,zz,1);
55             insert(xx,yyy,zzz,1);
56             insert(xxx,yy,zz,1);
57             insert(xxx,yy,zzz,1);
58             insert(xxx,yyy,zz,1);
59             insert(xxx,yyy,zzz,1);
60         }
61         else
62         {
63             printf("%d\n",getsum(xx,yy,zz)&1);
64         }
65     }
66     }
67 
68     return 0;
69 }
View Code

 

 

posted @ 2019-01-25 11:33  kaike  阅读(192)  评论(0编辑  收藏  举报