[树状数组]求逆序对
树状数组基本讲解:
树状数组的用途就是求前缀和,他的本质跟线段树相似,就是一个空间换时间。
主要采用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 }
求逆序对!
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 }
挖个坑下回把归并和快排的求逆序对放下来。
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 }
No matter how you feel, get up , dress up , show up ,and never give up.