這應該是幾乎人人都會的方法,原理是利用歸併排序時,對於區間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...