树状数组可以省时间而且省空间的求值和修改,相比于线段树来说代码量少,但我感觉树状数组求逆序数的功能更为强大,树状数组
可以利用从当前加入的数到最大全部添加的优势快速的使比当前加入的数大的所有数加一,省时省空间.
代码:
#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; }
原文地址:https://www.cnblogs.com/fzw1523/p/10268439.html
时间: 2024-11-01 11:41:10