主要要注意lowbit函数
然后add时向右跑,check时向左跑(此处的add只能单点修改)
1 #include<iostream>//从洛谷3374直接复制来的 2 #include<cstdio> 3 using namespace std; 4 #define lowbit(x) (x&(-(x))) 5 void read(int &x); 6 int n,m; 7 int a[500005]; 8 void add(int s,int t)//给s+t 9 { 10 int ss=s; 11 for(;ss<=n;ss+=lowbit(ss)) a[ss]+=t; 12 } 13 int check(int s,int t)//左闭右闭 14 { 15 int res=0; 16 int ret=0; 17 int ss=s-1; 18 int tt=t; 19 for(;tt;tt-=lowbit(tt)) ret+=a[tt]; 20 for(;ss;ss-=lowbit(ss)) res+=a[ss]; 21 return ret-res; 22 } 23 int main() 24 { 25 Read(n),Read(m); 26 int w; 27 for(int i=1;i<=n;i++) Read(w),add(i,w); 28 for(int i=1;i<=m;i++) 29 { 30 int e,s,t; 31 RRead(e),Read(s),Read(t); 32 if(e==1) add(s,t); 33 if(e==2) printf("%d ",check(s,t)); 34 } 35 return 0; 36 } 37 void Read(int &x) 38 { 39 x=0; 40 char c=getchar(); 41 int i=1; 42 while(c<'0' or c>'9') 43 { 44 if(c=='-') i=-1; 45 c=getchar(); 46 } 47 while(c>='0' and c<='9') 48 { 49 x=x*10+c-'0'; 50 c=getchar(); 51 } 52 x*=i; 53 }
若想实现区间修改,则要结合差分(不过这就只能单点查询了)
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 #define lowbit(x) ((x)&(-(x))) 5 void read(int &x); 6 int n,m; 7 int a[500005]; 8 int c[500005]; 9 void add(int s,int t)//给s+t 10 { 11 int ss=s; 12 for(;ss<=n;ss+=lowbit(ss)) a[ss]+=t; 13 } 14 int check(int s,int t)//左闭右闭 15 { 16 int res=0; 17 int ret=0; 18 int ss=s-1; 19 int tt=t; 20 for(;tt;tt-=lowbit(tt)) ret+=a[tt]; 21 for(;ss;ss-=lowbit(ss)) res+=a[ss]; 22 return ret-res; 23 } 24 int main() 25 { 26 read(n),read(m); 27 c[0]=0; 28 for(int i=1;i<=n;i++) read(c[i]); 29 for(int i=n;i>=1;i--) c[i]=c[i]-c[i-1]; 30 //for(int i=1;i<=n;i++) printf("*%d",a[i]); 31 for(int i=1;i<=n;i++) add(i,c[i]); 32 //for(int i=1;i<=n;i++) printf("*%d",check(1,i)); 33 for(int i=1;i<=m;i++) 34 { 35 int e,r; 36 read(e); 37 if(e==1) 38 { 39 int x,y,z; 40 read(x),read(y),read(z); 41 add(x,z); 42 add(y+1,(z*(-1))); 43 } 44 if(e==2) read(r),printf("%d ",check(1,r)); 45 } 46 return 0; 47 } 48 void read(int &x) 49 { 50 x=0; 51 char c=getchar(); 52 int i=1; 53 while(c<'0' or c>'9') 54 { 55 if(c=='-') i=-1; 56 c=getchar(); 57 } 58 while(c>='0' and c<='9') 59 { 60 x=x*10+c-'0'; 61 c=getchar(); 62 } 63 x*=i; 64 }
所以最强大的还是线段树了
1.树状数组可以实现平衡树
2.树状数组求逆序对(先离散化)
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5 #define lowbit(x) ((x)&(-(x))) 6 void Myread(long long &x); 7 void Mywrite(long long x); 8 long long n; 9 long long a[500005],c[500005]; 10 long long s[500005]; 11 long long sum(long long x) 12 { 13 long long z=0; 14 while(x) z+=s[x],x-=lowbit(x); 15 return z; 16 } 17 18 void add(long long x,long long p) 19 { 20 while(x<=n) s[x]+=p,x+=lowbit(x); 21 } 22 23 void li() 24 { 25 sort(c+1,c+1+n); 26 for(int i=1;i<=n;i++) a[i]=upper_bound(c+1,c+n+1,a[i])-(c+1); 27 } 28 int main() 29 { 30 Myread(n); 31 for(long long i=1;i<=n;i++) Myread(a[i]),c[i]=a[i]; 32 li(); 33 long long re=0; 34 for(int i=1;i<=n;i++) 35 { 36 add(a[i],1); 37 re+=sum(n)-sum(a[i]); 38 } 39 Mywrite(re); 40 return 0; 41 } 42 void Myread(long long &x) 43 { 44 long long i=1; 45 x=0; 46 char c=getchar(); 47 while(c<'0' or c>'9') 48 { 49 if(c=='-') i=-1; 50 c=getchar(); 51 } 52 while(c>='0' and c<='9') 53 { 54 x=x*10+(c-'0'); 55 c=getchar(); 56 } 57 x*=i; 58 } 59 void Mywrite(long long x) 60 { 61 if(x<0) 62 { 63 putchar('-'); 64 x=-1*x; 65 } 66 if(x>9) Mywrite(x/10); 67 putchar(x%10+'0'); 68 }
USACO11NOV(很清奇的想法)(将前缀和转换成逆序对)