树状数组相信大家都听说过,就是一大堆操作,lowbit然后附上一堆操作。具体就不说了
例题
例1:洛谷 模板1
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<math.h> 5 #define ll long long 6 #define file(a) freopen(a".in","r",stdin);//freopen(a".out","w",stdout); 7 const int maxn=500000+10; 8 inline int gi(){ 9 int sum=0,f=1;char ch=getchar(); 10 while(ch>‘9‘ || ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();} 11 while(ch>=‘0‘ && ch<=‘9‘){sum=sum*10+ch-‘0‘;ch=getchar();} 12 return sum*f; 13 } 14 inline ll gl(){ 15 ll sum=0,f=1;char ch=getchar(); 16 while(ch>‘9‘ || ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();} 17 while(ch>=‘0‘ && ch<=‘9‘){sum=sum*10+ch-‘0‘;ch=getchar();} 18 return sum*f; 19 } 20 ll c[maxn],a[maxn]; 21 int n; 22 int lowbit(int x){ 23 return x&(-x); 24 } 25 void Add(int x,ll d){ 26 while(x<=n){ 27 c[x]+=d; 28 x+=lowbit(x); 29 } 30 } 31 ll sum(int x){ 32 ll ans=0; 33 while(x){ 34 ans+=c[x]; 35 x-=lowbit(x); 36 } 37 return ans; 38 } 39 int main(){ 40 file("read"); 41 int i,j,m; 42 n=gi();m=gi(); 43 for(i=1;i<=n;i++){ 44 a[i]=gl(); 45 Add(i,a[i]); 46 } 47 for(i=1;i<=m;i++){ 48 int op=gi(),x=gi(); 49 if(op==1){ 50 ll k=gl(); 51 Add(x,k); 52 } 53 else{ 54 int y=gi(); 55 printf("%lld\n",sum(y)-sum(x-1)); 56 } 57 } 58 return 0; 59 } 60 /* 61 输入格式: 62 第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。 63 第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。 64 接下来M行每行包含3个整数,表示一个操作,具体如下: 65 操作1: 格式:1 x k 含义:将第x个数加上k 66 操作2: 格式:2 x y 含义:输出区间[x,y]内每个数的和 67 输出格式: 68 输出包含若干行整数,即为所有操作2的结果。 69 */
例2:洛谷 模板2
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<math.h> 5 #define ll long long 6 #define file(a) freopen(a".in","r",stdin);//freopen(a".out","w",stdout); 7 const int maxn=500000+10; 8 inline int gi(){ 9 int sum=0,f=1;char ch=getchar(); 10 while(ch>‘9‘ || ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();} 11 while(ch>=‘0‘ && ch<=‘9‘){sum=sum*10+ch-‘0‘;ch=getchar();} 12 return sum*f; 13 } 14 inline ll gl(){ 15 ll sum=0,f=1;char ch=getchar(); 16 while(ch>‘9‘ || ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();} 17 while(ch>=‘0‘ && ch<=‘9‘){sum=sum*10+ch-‘0‘;ch=getchar();} 18 return sum*f; 19 } 20 int n; 21 ll c[maxn],a[maxn]; 22 int lowbit(int x){ 23 return x&(-x); 24 } 25 void Add(int x,ll d){ 26 while(x<=n){ 27 c[x]+=d; 28 x+=lowbit(x); 29 } 30 } 31 ll sum(int x){ 32 ll ans=0; 33 while(x){ 34 ans+=c[x]; 35 x-=lowbit(x); 36 } 37 return ans; 38 } 39 int main(){ 40 file("read"); 41 int i,j,m; 42 n=gi();m=gi(); 43 for(i=1;i<=n;i++){ 44 a[i]=gl(); 45 Add(i,a[i]-a[i-1]); 46 } 47 for(i=1;i<=m;i++){ 48 int op=gi(),x=gi(); 49 if(op==1){ 50 int y=gi();ll k=gl(); 51 Add(x,k); 52 Add(y+1,-k); 53 } 54 else{ 55 printf("%lld\n",sum(x)); 56 } 57 } 58 return 0; 59 }
例3:洛谷 逆序对
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<math.h> 5 #include<algorithm> 6 using namespace std; 7 #define ll long long 8 #define file(a) freopen(a".in","r",stdin);//freopen(a".out","w",stdout); 9 const int maxn=40000+10; 10 inline int gi(){ 11 int sum=0,f=1;char ch=getchar(); 12 while(ch>‘9‘ || ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();} 13 while(ch>=‘0‘ && ch<=‘9‘){sum=sum*10+ch-‘0‘;ch=getchar();} 14 return sum*f; 15 } 16 int n; 17 int a[maxn],b[maxn],c[maxn]; 18 int lowbit(int x){ 19 return x&(-x); 20 } 21 void Add(int x,int d){ 22 while(x<=n){ 23 c[x]+=d; 24 x+=lowbit(x); 25 } 26 } 27 int sum(int x){ 28 int ans=0; 29 while(x){ 30 ans+=c[x]; 31 x-=lowbit(x); 32 } 33 return ans; 34 } 35 int main(){ 36 file("read"); 37 int i,j,k,m; 38 int ans=0; 39 n=gi(); 40 for(i=1;i<=n;i++)a[i]=b[i]=gi(); 41 sort(b+1,b+n+1); 42 for(i=1;i<=n;i++) 43 a[i]=lower_bound(b+1,b+n+1,a[i])-b; 44 for(i=1;i<=n;i++){ 45 Add(a[i],1); 46 ans+=i-sum(a[i]); 47 } 48 printf("%d\n",ans); 49 return 0; 50 }