zoj 1484 Minimum Inversion Number(树状数组||线段树)

来源:互联网 发布:java修改文件夹权限 编辑:程序博客网 时间:2024/05/01 23:52

树状数组很经典的运用,求逆序数。

题意是要求将数移到最后位置时,最小的逆序数。求一个序列的逆序数可以通过树状数组或者线段树做。树状数组还是很巧妙的,每次读入一个数,将该数存入树状数组C[],查询前面是否有比该数大的数,即为逆序数。

数状数组代码:

#include<stdio.h>#include<string.h>int C[5005],n;int lowbit(int x){    return x&(-x);}int query(int x){    int sum=0;    x+=1;    while(x<=n){        sum+=C[x];        x+=lowbit(x);    }    return sum;}void update(int pos,int val){    while(pos>0){        C[pos]+=val;        pos-=lowbit(pos);    }}int main(){    int sum,x,a[5005];    while(~scanf("%d",&n)){        sum=0;        memset(C,0,sizeof(C));        for(int i=0;i<n;i++){            scanf("%d",&a[i]);            update(a[i]+1,1);            sum+=query(a[i]+1);        }        int min=sum;      //  printf("%d\n",sum);        for(int i=0;i<n;i++){            sum=sum+(n-1)-2*a[i];            if(sum<min) min=sum;        }        printf("%d\n",min);    }    return 0;}
线段树代码:

#include <iostream>#include<cstdio>using namespace std;//#define min(a,b)a>b?b:a#define lson    l,m,rt<<1#define rson    m+1,r,rt<<1|1const int maxn=5005;int sum[maxn<<2];int a[maxn];void pushup(int rt){    sum[rt]=sum[rt<<1]+sum[rt<<1|1];}void build(int l,int r,int rt){    if(l==r){        sum[rt]=0;        return;    }    int m=(l+r)>>1;    build(lson);    build(rson);    pushup(rt);}int query(int L,int R,int l,int r,int rt){    if(L<=l&&r<=R){        return sum[rt];    }    int ret=0;    int m=(l+r)>>1;    if(L<=m)    ret+=query(L,R,lson);    if(R>m) ret+=query(L,R,rson);    return ret;}void update(int p,int l,int r,int rt){    if(l==r){        sum[rt]++;return;}    int m=(l+r)>>1;    if(p<=m)    update(p,lson);    else    update(p,rson);    pushup(rt);}int main(){    int n;    while(~scanf("%d",&n)){        build(0,n-1,1);        int sum=0;        for(int i=0;i<n;i++){            scanf("%d",&a[i]);            sum+=query(a[i],n-1,0,n-1,1);            update(a[i],0,n-1,1);        }        int res=sum;        for(int j=0;j<n;j++){sum=sum-a[j]+(n-a[j]-1);            res=min(res,sum);        }        printf("%d\n",res);    }    return 0;}


原创粉丝点击