逆序對的三種求法 歸併排序,樹狀陣列,線段樹

2022-05-19 22:21:45 字數 1740 閱讀 7082

這應該是幾乎人人都會的方法,原理是利用歸併排序時,對於區間l~r,在mid左邊和mid右邊都已經是單調的序列來求逆序對,這種方法就不多講了。時間複雜度約為o(nlogn)

**如下:個人習慣打快讀

#includeusing namespace std;

const int maxn=1e6+10;

templatevoid read(t&res)

res=(ch^48);

while((ch=getchar())>='0' and ch<='9')

res=(res<<1)+(res<<3)+(ch^48);

res*=q;

return;

}int n,a[maxn];

long long ans;

inline void init()

//歸併排序

int temp[maxn];

void merge_sort(int l,int r)

while(l<=mid)temp[ll++]=a[l++];

while(rr<=r)temp[ll++]=a[rr++];

for(int i=st;i<=r;i++)

a[i]=temp[i];

return;

}int main()

res=(ch^48);

while((ch=getchar())>='0' and ch<='9')

res=(res<<1)+(res<<3)+(ch^48);

res*=q;

return;

}int n,a[maxn];

long long ans;

inline void init()

//樹狀陣列

int tree[maxn];

inline int lowbit(int x)

inline void add(int x,int v)

return;

}inline int sum(int x)

return res;

}void solve()

res=(ch^48);

while((ch=getchar())>='0' and ch<='9')

res=(res<<1)+(res<<3)+(ch^48);

res*=q;

return;

}int n,a[maxn];

long long ans;

inline void init()

//權值線段樹

structe[maxn*3];

void build(int k,int l,int r)

void update(int k,int num)

int mid=(e[k].l+e[k].r)>>1;

if(num<=mid)update(k<<1,num);

if(num>mid)update(k<<1|1,num);

e[k].tot=e[k<<1].tot+e[k<<1|1].tot;

return;

}long long sum(int k,int l,int r)

{ if(e[k].l>r or e[k].r>1;

if(mid>=r)return sum(k<<1,l,r);

if(mid對於我個人而言還是比較喜歡樹狀陣列的,因為比較短。當然這也只是個人意見。

逆序對 (樹狀陣列 歸併排序

陣列前面的乙個元素 大於等於 後面的乙個元素就是乙個逆序對 樹狀陣列可以快速求字首和,利用這一特性,可以求逆序對個數,見下 用陣列c i 記錄陣列a n 中i這一元素出現的次數 當a n 中元素較大時可以離散化處理。將a n 從a n 1 到a 0 依次存到樹狀陣列中,每存乙個,對存的元素i求一次c...

求逆序對(歸併排序 樹狀陣列)

兩種演算法的時間複雜度都是 o nlogn 但是,有可能樹狀陣列需要離散化!所以,由許多元素共同影響下,歸併排序求逆序對 比 樹狀陣列求逆序對 歸併排序 include define ll long long define n 100005 using namespace std int a n t...

求逆序對 樹狀陣列 歸併排序模板

ps 但資料大的時候,需要離散化陣列會多乙個排序的複雜的,其實還不如歸併找逆序對塊 歸併找逆序對也是o n logn 樹狀陣列 include include include include include include includeusing namespace std const int i...