今天复习了一下树状数组,顺便学了一下如何求逆序对。
首先是树状数组单点修改+区间和,但有一点需要注意,就是getsum函数里是now-=lowbit(now),但是update()里或add()里一定是now += lowbit(now);
#include<cstdio> #include<iostream> using namespace std; const int MAXN = 1e5 + 5; int n,c[MAXN],a[MAXN],m; int lowbit(int x) { return x & -x; } int getsum(int now) { int sum = 0; while(now > 0) { sum += c[now]; now -= lowbit(now); } return sum; } void update(int l,int v) { while(l <= n) c[l] += v,l += lowbit(l); } /*int build_tree(int x) { int ret = 0; while(x > 0) { ret += c[pos]; pos -= lowbit(pos); } return ret; }*/ int main() { int c,d,e; cin>>n>>m; for(int i = 1;i <= n;i++) { cin>>a[i]; update(i,a[i]); } for(int i = 1;i <= m;i++) { cin>>c>>d>>e; if(c == 1) { update(d,e); } else { // cout<<getsum(e)<<" "<<getsum(d - 1)<<endl; cout<<getsum(e) - getsum(d - 1)<<endl; } } return 0; }
然后是区间修改+单点求值,和单点修改有不同,主要是一开始不把数放进数组,然后假如要把d~f区间加上n,就先把d之后的都加上,然后减去f+1之后的就行了。
#include<cstdio> #include<iostream> using namespace std; const int MAXN = 1e7 + 5; int n,c[MAXN],a[MAXN],m,input[MAXN],g; int lowbit(int x) { return x & -x; } int getsum(int now) { int sum = 0; while(now > 0) { sum += c[now]; now -= lowbit(now); } return sum; } void update(int l,int v) { while(l <= n) c[l] += v,l += lowbit(l); } /*int build_tree(int x) { int ret = 0; while(x > 0) { ret += c[pos]; pos -= lowbit(pos); } return ret; }*/ int main() { int d,e,f; cin>>n>>m; for(int i = 1;i <= n;i++) { cin>>a[i]; // update(i,a[i]); } for(int i = 1;i <= m;i++) { cin>>g; if(g == 1) { cin>>d>>e>>f; update(d,f); update(e + 1,-f); } else { cin>>d; cout<<getsum(d) + a[d]<<endl; } } return 0; }
最后,是求逆序对。先把这些数(结构体里再存一个编号)按照从大到小排序,(就算是离散化了,然后和原数就没关系了),然后向数组中插入编号,每次计算前面的和。注意,getsum里传入的是编号,而且必须传的是num-1.
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; int c[40005],a[40005],n; struct node{ int k,c; }; node d[40055]; int lowbit(int x) { return x & -x; } int getsum(int now) { int sum = 0; while(now > 0) { sum += c[now]; now -= lowbit(now); } return sum; } int add(int now,int k) { while(now < n) { c[now] += k; now += lowbit(now); } } bool cmp(node x,node y) { return x.k > y.k; } int main() { int ans = 0; cin>>n; for(int i = 1;i <= n;i++) { d[i].c = i; cin>>d[i].k; } sort(d + 1,d + n + 1,cmp); for(int i = 1;i <= n;i++) { add(d[i].c,1); ans += getsum(d[i].c - 1); } cout<<ans<<endl; return 0; }