求逆序对的两种方法(树状数组/归并排序)

例题:poj2299

看代码就好了

树状数组:

#include<iostream>
#include<cstdio>
#include<queue>
#include<string>
#include<string.h>
#include<set>
#include<stack>
#include<vector>
#include<algorithm>
#include<cmath>
#include<iterator>
#define mem(a,b) memset(a,b,sizeof(a))
#define MOD 100000007
#define ll long long
#define INF 0x3f3f3f3f
const double pi = acos(-1.0);
const int Maxn=50000;
using namespace std;
inline int scan()
{
    int x=0,c=1;
    char ch=' ';
    while((ch>'9'||ch<'0')&&ch!='-')ch=getchar();
    while(ch=='-')c*=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();
    return x*c;
}
/**********************************树状数组+离散化*******************************/
ll c[500010];
ll n;
ll lowbit(ll x){
    return x&-x;
}
void add(ll i){
    while(i<=n){
        c[i]++;
        i+=lowbit(i);
    }
}
ll getnum(ll i){
    ll num=0;
    while(i>0){
        num+=c[i];
        i-=lowbit(i);
    }
    return num;
}
struct node{
    ll v,i;
    friend bool operator < (node a,node b){
        return a.v<b.v;
    }
}nd[500010];
int main(){
    while(scanf("%lld",&n)&&n){
        mem(nd,0);
        mem(c,0);
        map<int,int>mp;
        int v;
        ll k=0;
        for(int i=1;i<=n;i++){
            scanf("%d",&v);
            if(!mp[v]){//要去重!!! 
                nd[++k].v=v;
                nd[k].i=k;
                mp[v]=1;
            }
        }
        n=k;
        sort(nd+1,nd+n+1);
        ll ans=0;
        for(int i=1;i<=n;i++){
            add(nd[i].i);
            ans+=(1ll*i-getnum(nd[i].i));//已插入i个数,getnum[nd[i].i]是比nd[i].i小的数的个数i-getnum[nd[i].i]就是i个数前比他大的数
        }
        printf("%lld
",ans);
    }
    return 0;
}

归并排序:

#include<iostream>
#include<cstdio>
#include<queue>
#include<string>
#include<string.h>
#include<set>
#include<stack>
#include<vector>
#include<algorithm>
#include<cmath>
#include<iterator>
#define mem(a,b) memset(a,b,sizeof(a))
#define MOD 100000007
#define ll long long
#define INF 0x3f3f3f3f
const double pi = acos(-1.0);
const int Maxn=50000;
using namespace std;
inline int scan()
{
    int x=0,c=1;
    char ch=' ';
    while((ch>'9'||ch<'0')&&ch!='-')ch=getchar();
    while(ch=='-')c*=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();
    return x*c;
}
int c[500010];
vector<int>vec;
int n;
ll ans;
void mergersort(int l,int r){
    if(l==r){
        return ;
    }
    int mid=(l+r)>>1;
    mergersort(l,mid);
    mergersort(mid+1,r);
    vec.clear();
    int q=l,p=mid+1;
    while(q<=mid&&p<=r){
        if(c[q]<=c[p]){
            vec.push_back(c[q++]);
        }else{
            vec.push_back(c[p++]);
            ans+=(mid-q+1);///l~mid中剩余数的个数就是mid-q+1,而如果c[q]>c[p],那c[p]就要交换mid-q+1次
        }
    }
    while(q<=mid) vec.push_back(c[q++]);
    while(p<=r) vec.push_back(c[p++]);
    q=l;
    for(int i=0;i<vec.size();i++){
        c[q++]=vec[i];
    }
}
int main(){
    while(scanf("%d",&n)&&n){
        ans=0;
        mem(c,0);
        for(int i=1;i<=n;i++){
            scanf("%d",&c[i]);
        }
        mergersort(1,n);
        printf("%lld
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/liuzuolin/p/10827554.html