陣列前面的乙個元素 大於等於 後面的乙個元素就是乙個逆序對;
樹狀陣列可以快速求字首和,利用這一特性,可以求逆序對個數,見下:
用陣列c[ i ]記錄陣列a[ n ]中i這一元素出現的次數 ,當a[ n ]中元素較大時可以離散化處理。
將a[ n ]從a[n -1]到a[0] 依次存到樹狀陣列中,每存乙個,對存的元素i求一次c[i]的字首和, 這就是當前已掃瞄過的比i小的元素的個數,由於a[n]是倒著掃瞄的,所以此時比i小的元素都對應乙個逆序對,統計之。
#include #include#include
using
namespace
std;
int c[600000
];int a[600000] ,b[600000
];int
n;long
long
ans;
int lowbit( int
x)void updata( int x ,intv)}
int getsum( int
x)
returns;}
intmain( )
sort( b ,b + n); //
離散化處理
int sz = unique( b ,b+n) -b;
ans = 0
;
for( int i=n-1 ;i >=0 ;i--)
printf(
"%lld\n
",ans);
}return0;
}
歸併排序求逆序對在lrj的高效演算法設計一章學過,不過又把一些細節忘了:
1) 分治的引數x,y是左閉右開的,就是(n-1是陣列末項下標 (0,n)->( 0,m ),(m ,n )
2) 分治條件y-x>1,因為y是開的,碰不到,y-x==1就是只有乙個元素不能再分的情況了
3) 求逆序對時是 cnt += m-p,有半部分有乙個小的左半部分沒排的(m-p個)都是比他大的
#include #include#include
#include
using
namespace
std;
int a[600000
];int b[600000
];int
n;long
long
ans;
void ergesort( int x ,int
y)
for( int i=x ; ib[ i];
return;}
intmain( )
ergesort(
0,n);
//for( int i=0 ;iprintf( "
%lld\n
",ans);
}return0;
}
求逆序對(歸併排序 樹狀陣列)
兩種演算法的時間複雜度都是 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...
poj 2299(逆序對(樹狀陣列 歸併排序))
題目鏈結 題目大意 在這個問題中,你必須分析乙個特定的排序演算法。該演算法通過交換兩個相鄰的序列元素來處理n個不同整數的序列,直到序列按公升序排序。對於輸入序列 9 1 0 5 4,通過ultra quicksort輸出 0 1 4 5 9。你的任務是確定ultra quicksort需要執行多少交...