1. 程式人生 > >poj2299樹狀陣列入門,求逆序對

poj2299樹狀陣列入門,求逆序對

今天入門了樹狀陣列 習題連結 https://blog.csdn.net/liuqiyao_01/article/details/26963913

離散化資料:用一個數組來記錄每個值在數列中的排名,不能用map,會超時

開結構體儲存每個數在數列中原來的位置,排序後用a陣列求出原來狀態下每個數的排名。

/*
線段樹求逆序對的話是按順序把數字插到數字對應的線段樹下標裡,然後統計該下標右邊的數個數
樹狀陣列求逆序對思路:按順序一個個插到陣列中,統計比它小的個數,逆序數=當前數的下標-當前比它小的個數

*/
#include<iostream>
#include<cstring>
#include
<cstdio> #include<algorithm> #define maxn 500500 #define ll long long using namespace std; struct node{ int val,pos; bool operator<(const node & a)const { return val<a.val; } }p[maxn]; int n,bit[maxn],a[maxn]; //樹狀陣列bit[i]維護的資訊是排名在一個區間內的數字個數 //陣列a表示第i個數的排名是多少 void add(int
i){ while(i<=n){ bit[i]+=1; i+=i&-i; } } int sum(int i){ int s=0; while(i>0){ s+=bit[i]; i-=i&-i; } return s; } void solve(){ for(int i=1;i<=n;i++){scanf("%d",&p[i].val);p[i].pos=i;} sort(p+1,p+1+n); for(int i=1;i<=n;i++)a[p[i].pos]=i; memset(bit,
0,sizeof bit); ll ans=0; for(int i=1;i<=n;i++){ add(a[i]);//排名為a[i]的地方加1 ans+=i-sum(a[i]);//當前所有被加入的數個數-排名在第i的數之前的數=增加的逆序對數 } printf("%lld\n",ans); } int main(){ while(scanf("%d",&n),n)solve(); }