欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

求逆序对+树状数组/归并排序模板

程序员文章站 2022-05-10 15:12:37
...

PS 但数据大的时候,需要离散化数组会多一个排序的复杂的,其实还不如归并找逆序对块

归并找逆序对也是O(n*logn)

树状数组:

#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<stdlib.h>
#include<vector> 
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1000000;
typedef long long ll; 
vector<int> v;//当数值很大的时候离散化 
int getid(int x){//得到离散化后的下标 
	return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
int n,m,a[maxn];
int c[maxn];
int lowbit(int x) {
      return x&-x; 
}
void add(int id, int p){//处理的是下标 
    while(id <= n){
        c[id] += p;
        id += lowbit(id);
    }
}
int sum(int id){//求前I项的和 
    int ans = 0;
    while(id >= 1){
        ans += c[id];
        id -= lowbit(id);
    }
    return ans;
}
int main(){
	while(cin>>n){
		if(n==0) break;
		v.clear();
	for(int i=1;i<=n;i++){
		cin>>a[i];
		c[i]=0;//注意 
		v.push_back(a[i]);
	}
	sort(v.begin(),v.end());
	v.erase(unique(v.begin(),v.end()),v.end());
	ll ans=0;
	for(int i=1;i<=n;i++){
		add(getid(a[i]),1);
		int tmp=i-sum(getid(a[i]));
		ans+=tmp;
	} 
	cout<<ans<<endl;
    }
}

归并排序:

#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<stdlib.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1000000;
typedef long long ll;
int a[maxn];
int b[maxn];//辅助数组 
ll ans;//逆序对数 
void merge_sort(int l,int r){
	if(l==r) return ;
	int k=l;
	int mid=(l+r)/2;
	int i=l;int j=mid+1;
	merge_sort(i,mid);
	merge_sort(j,r);
	while(i<=mid&&j<=r){//两部分都未跑完时 
		if(a[i]<=a[j]) b[k++]=a[i++];
		else ans+=mid-i+1,b[k++]=a[j++];
	}
	while(i<=mid) b[k++]=a[i++];//继续跑完剩下的部分 
	while(j<=r) b[k++]=a[j++];
	for(int p=l;p<=r;p++) a[p]=b[p];//将b中排好的元素放回去 
}
int main(){
	int n; 
	while(cin>>n){
		if(n==0) break;
		ans=0;
	for(int i=1;i<=n;i++) cin>>a[i];
	merge_sort(1,n);
//	for(int i=1;i<=n;i++) cout<<a[i]<<" ";
    cout<<ans<<endl;
    }
	return 0;
}