树状数组求逆序数及变形(个人理解)
Posted fzw1523
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树状数组求逆序数及变形(个人理解)相关的知识,希望对你有一定的参考价值。
树状数组可以省时间而且省空间的求值和修改,相比于线段树来说代码量少,但我感觉树状数组求逆序数的功能更为强大,树状数组
可以利用从当前加入的数到最大全部添加的优势快速的使比当前加入的数大的所有数加一,省时省空间.
代码:
#include<bits/stdc++.h> using namespace std; int x[100010]; int szsz[100010]; int lowbit(int a){ return a&(-a); } void add(int a){ for(int i=a;i<=100000;i+=lowbit(i)){ szsz[i]+=1; } } int qiuhe(int a){ int ans=0; for(int i=a;i>=1;i-=lowbit(i)){ ans+=szsz[i]; } return max(ans-1,0); } int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&x[i]); } memset(szsz,0,sizeof(szsz)); int start,eend; // start代表从几号开始,eend代表到几号结束,求中间的逆序数个数 、 scanf("%d %d",&start,&eend); for(int i=start;i<=eend;i++){ add(x[i]); printf("%d ",qiuhe(99999)-qiuhe(x[i])); } printf("\n"); return 0; }
但对于题目来说单单求逆序数就很没意思了,例如让你求 x > y 时 ax<y 的个数,这种呢主要看你对于逆序数和公式的理解,一般来说
这种题目比较简单的,因为观察可知qiuhe(MAX_N)- qiuhe(x[ i ])后面打入的是x[ i ],所以得出的是对于X[ i ]的逆序数,综上所述,如
果想得到 y 的逆序数只需要打入 y 即可.
例题 https://codeforces.com/problemset/problem/961/E
ac代码 :
#include<bits/stdc++.h> using namespace std; int x[200020]; int szsz[200020]; int m,n; vector <int> vic[200020]; int lowbit(int a){ return a&(-a); } void add(int a){ for(int i=a;i<=200015;i+=lowbit(i)){ szsz[i]+=1; } } int qiuhe(int a){ int ans=0; for(int i=a;i>=1;i-=lowbit(i)){ ans+=szsz[i]; } return ans; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&x[i]); x[i]=min(n,x[i]); vic[min(i-1,x[i])].push_back(i); } memset(szsz,0,sizeof(szsz)); long long sum=0; for(int i=1;i<=n;i++){ add(x[i]); for(int j=0;j<vic[i].size();j++){ sum+=qiuhe(n)-qiuhe(vic[i][j]-1); } } printf("%lld\n",sum); return 0; }
以上是关于树状数组求逆序数及变形(个人理解)的主要内容,如果未能解决你的问题,请参考以下文章