樹狀數組求逆序數及變形(個人理解)
阿新 • • 發佈:2019-01-14
%d sca def 優勢 得到 back names add start
樹狀數組可以省時間而且省空間的求值和修改,相比於線段樹來說代碼量少,但我感覺樹狀數組求逆序數的功能更為強大,樹狀數組
可以利用從當前加入的數到最大全部添加的優勢快速的使比當前加入的數大的所有數加一,省時省空間.
代碼:
#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; }
樹狀數組求逆序數及變形(個人理解)