树状数组
一.单点修改,区间查询
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const ll N=5*1e5+2; 5 inline int read() 6 { 7 ll sm=0,flag=1; 8 char ch=getchar(); 9 while(ch<'0'||ch>'9'){if(ch=='-')flag=-1;ch=getchar();} 10 while(ch>='0'&&ch<='9'){sm=sm*10+ch-'0';ch=getchar();} 11 return sm*flag; 12 } 13 ll n,m; 14 ll c[N]; 15 ll lowbit(ll x) 16 { 17 return x&(-x); 18 } 19 void uphold(ll x,ll num) 20 { 21 while(x<=n) 22 { 23 c[x]+=num; 24 x+=lowbit(x); 25 } 26 } 27 ll ask(ll x) 28 { 29 ll ans=0; 30 while(x>=1) 31 { 32 ans+=c[x]; 33 x-=lowbit(x); 34 } 35 return ans; 36 } 37 int main() 38 { 39 n=read();m=read(); 40 for(ll i=1;i<=n;++i) 41 { 42 ll a=read(); 43 uphold(i,a); 44 } 45 for(ll i=1;i<=m;++i) 46 { 47 ll type=read(); 48 if(type==1) 49 { 50 ll x=read(),k=read(); 51 uphold(x,k); 52 } 53 else if(type==2) 54 { 55 ll x=read(),y=read(); 56 cout<<ask(y)-ask(x-1)<<endl; 57 } 58 } 59 return 0; 60 }
二.区间修改,单点查询
运用了前缀和的思想
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const ll N=5*1e5+2; 5 inline int read() 6 { 7 ll sm=0,flag=1; 8 char ch=getchar(); 9 while(ch<'0'||ch>'9'){if(ch=='-')flag=-1;ch=getchar();} 10 while(ch>='0'&&ch<='9'){sm=sm*10+ch-'0';ch=getchar();} 11 return sm*flag; 12 } 13 ll n,m; 14 ll c[N]; 15 ll lowbit(ll x) 16 { 17 return x&(-x); 18 } 19 void uphold(ll x,ll num) 20 { 21 while(x<=n) 22 { 23 c[x]+=num; 24 x+=lowbit(x); 25 } 26 } 27 ll ask(ll x) 28 { 29 ll ans=0; 30 while(x>=1) 31 { 32 ans+=c[x]; 33 x-=lowbit(x); 34 } 35 return ans; 36 } 37 int main() 38 { 39 n=read();m=read(); 40 ll last=0; 41 for(ll i=1;i<=n;++i) 42 { 43 ll x=read(); 44 uphold(i,x-last); 45 last=x; 46 } 47 for(ll i=1;i<=m;++i) 48 { 49 ll type=read(); 50 if(type==1) 51 { 52 ll x=read(),y=read(),z=read(); 53 uphold(x,z);uphold(y+1,-1*z); 54 } 55 else if(type==2) 56 { 57 ll x=read(); 58 cout<<ask(x)<<endl; 59 } 60 } 61 return 0; 62 }
三.求逆序对
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int maxn = 100010; 5 const int maxm = 99999997; 6 struct MyStruct 7 { 8 int data; 9 int loc; 10 }a[maxn],b[maxn]; 11 int e[maxn], n, c[maxn]; 12 int inline readint() 13 { 14 int x = 0; 15 char c = getchar(); 16 while (c<'0' || c>'9') c = getchar(); 17 while (c >= '0'&&c <= '9') 18 { 19 x = x * 10 + c - '0'; 20 c = getchar(); 21 } 22 return x; 23 } 24 int lowbit(int x) 25 { 26 return x&-x;//树状数组实现 27 } 28 void add(int x,int t) 29 { 30 while (x <= n) 31 { 32 e[x] += t; 33 e[x] %= maxm; 34 x += lowbit(x);//每次往后加,可以改变后面对应的和 35 } 36 } 37 int sum(int x) 38 { 39 int s = 0; 40 while(x) 41 { 42 s += e[x]; 43 s %= maxm; 44 x -= lowbit(x);//得到所求的和 45 } 46 return s; 47 } 48 bool cmp(MyStruct x, MyStruct y) 49 { 50 return x.data < y.data; 51 } 52 int main() 53 { 54 n = readint(); 55 for (int i = 1; i <= n; i++) 56 { 57 a[i].data = readint(); 58 a[i].loc = i;//记录位置 59 } 60 for (int i = 1; i <= n; i++) 61 { 62 b[i].data = readint(); 63 b[i].loc = i; 64 } 65 sort(a + 1, a + n + 1, cmp); 66 sort(b + 1, b + n + 1, cmp); 67 for (int i = 1; i <= n; i++) 68 { 69 c[a[i].loc] = b[i].loc;//离散优化 70 } 71 int ans = 0; 72 for (int i = 1; i <= n; i++) 73 { 74 add(c[i], 1);//离散优化后大小就是正确顺序的位置 75 ans += i - sum(c[i]);//当前位置,减去之前比他大的数的个数 76 ans %= maxm; 77 } 78 printf("%d", ans); 79 return 0; 80 }