求逆序对+树状数组/归并排序模板
程序员文章站
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;
}
上一篇: HTML学习笔记02--常见标签
下一篇: 排序模板+求逆序对(归并的思想)