【luogu1908/1774】 逆序对 [逆序对][树状数组][线段树]

1908 逆序对

 1774 最接近神的人_NOI导刊2010提高(02)

经欧阳讲解后我好像 似乎 理解了     资料

 mergesort

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define ll long long
#define rg register
#define Max(x,y) (x)>(y)?(x):(y)
#define Min(x,y) (x)>(y)?(y):(x)
const int N=500000+5,M=200000+5,inf=0x3f3f3f3f,P=19650827;
int n,a[N],rk[N];
ll ans=0ll;
template <class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

void mergesort(int l,int r){
    if(l>=r) return;
    int mid=(l+r)>>1,pl=l,pr=mid+1,k=l;
    mergesort(l,mid),mergesort(mid+1,r);
    while(pl<=mid&&pr<=r)
    if(a[pl]<=a[pr]) rk[k++]=a[pl++];
    else rk[k++]=a[pr++],ans+=(ll)mid-pl+1;
    while(pl<=mid) rk[k]=a[pl],++k,++pl;
    while(pr<=r) rk[k]=a[pr],++k,++pr;
    for(int i=l;i<=r;++i) a[i]=rk[i];
}

int main(){
//    freopen("in.txt","r",stdin);
    rd(n);
    for(int i=1;i<=n;++i) rd(a[i]);
    mergesort(1,n);
    printf("%lld",ans);
    return 0;
}
 

 树状数组

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define ll long long
#define rg register
#define Max(x,y) (x)>(y)?(x):(y)
#define Min(x,y) (x)>(y)?(y):(x)
const int N=500000+5,M=200000+5,inf=0x3f3f3f3f,P=19650827;
ll n,a[N],tree[N<<1],b[N];
ll sum=0;
template <class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

int lowbit(int x) {return x&(-x);}

void update(int pos,int ad){
    while(pos<=n) tree[pos]+=ad,pos+=lowbit(pos);
}

bool cmp(int x,int y){return a[x]==a[y]?x>y:a[x]>a[y];}

ll query(int pos){
    ll ans=0;
    while(pos>0) ans+=tree[pos],pos-=lowbit(pos);
    return ans;
}

int main(){
//    freopen("in.txt","r",stdin);
    rd(n);
    for(int i=1;i<=n;++i) rd(a[i]),b[i]=i;
    sort(b+1,b+1+n,cmp);
    for(int i=1;i<=n;++i) update(b[i],1),sum+=query(b[i]-1);//比自己小且在自己后面
     printf("%lld",sum);
    return 0;
}
 

 存一个只有50昏的动态开点

#include<bits/stdc++.h>
using namespace std;
#define Max(x,y) (x)<(y)?(y):(x)
#define Min(x,y) (x)<(y)?(x):(y)
#define ll long long
#define rg register
const int N=1e9,M=7e5+5,inf=0x3f3f3f3f,P=9999973;
const int power=4,base=10000;
ll n,a[M],cnt=1,lson[M],rson[M],sum[M];
ll ans=0;
template <class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

void pushup(int o){
    sum[o]=sum[lson[o]]+sum[rson[o]];
}

void add(int o,int l,int r,int k){
    if(l>r) return;
    if(l==r){
        ++sum[o];
        return;
    }
    if(l>r) return;
    int mid=l+r>>1;
    if(k<=mid){
        if(!lson[o]) lson[o]=++cnt;
        add(lson[o],l,mid,k);
    }
    else{
        if(!rson[o]) rson[o]=++cnt;
        add(rson[o],mid+1,r,k);
    }
    pushup(o);
}

ll query(int o,int l,int r,int k){
    if(!o||l>r) return 0;
    if(l==r) return sum[o];
    int mid=l+r>>1;
    if(k<=mid) return query(lson[o],l,mid,k);
    else return sum[lson[o]]+query(rson[o],mid+1,r,k);
}


int main(){
    freopen("in.txt","r",stdin);
    rd(n);
    for(int i=1;i<=n;++i) rd(a[i]);
    for(int i=n;i;--i){
        ans+=query(1,1,N+5,a[i]-1);
        add(1,1,N+5,a[i]);
    }
    printf("%lld",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/lxyyyy/p/11178011.html