hdu1394 线段树 / 树状数组

来源:互联网 发布:js获取指定日期前一天 编辑:程序博客网 时间:2024/06/08 13:34

题目:就是求一个数组的逆序数,然后依次将数组的第一个数调到最后,最后求出最小的逆序数


做了两种,线段树和树状数组

//利用线段树求逆序数 // 每次将数字x插到线段树的 x 位置,然后球一下,该线段树右边的和,即为逆序数的个数 //第一次用线段树,做这个。。 #include<iostream>#include<cstdio>#include<cstring>#include<vector>#include<algorithm>using namespace std;#define maxn 5555int sum[maxn<<2];int x[maxn];/*void build(int l,int r,int rt)//其实build 可以省略 {    sum[rt]=0;   if(l==r)return ;   int mid=(l+r)>>1;   build(l,mid,rt<<1);   build(mid+1,r,rt<<1|1);   }*/void build(int l,int r,int rt){memset(sum,0,sizeof(sum));} void push_up(int rt){sum[rt]=sum[rt<<1]+sum[rt<<1|1];}void update(int p,int l,int r,int rt){if(l==r){sum[rt]++; //而不是直接赋值为1,因为还可能有重复的值插入return ; }int mid=(l+r)>>1;if(p<=mid)update(p,l,mid,rt<<1);else update(p,mid+1,r,rt<<1|1);push_up(rt);}int query(int L,int R,int l,int r,int rt){if(L<=l && R>=r)return sum[rt];int mid=(l+r)>>1;int res=0;if(L<=mid)res+=query(L,R,l,mid,rt<<1);if(R>mid)res+=query(L,R,mid+1,r,rt<<1|1);return res;}int main(){//freopen("q.in","r",stdin);int n;int i,j;    while(~scanf("%d",&n))    {    int ret=0;    memset(x,0,sizeof(x));build(0,n-1,1);for(i=0;i<n;i++){scanf("%d",&x[i]);ret+=query(x[i],n-1,0,n-1,1); update(x[i],0,n-1,1);}int ans=ret;for(i=0;i<n;i++){ret+=n-x[i]-x[i]-1;ans=min(ret,ans);//最后找出所有序列中的最小逆序数 }cout<<ans<<endl;    }} 

#include <cstdio>#include<cmath>#include<cstring>#include<iostream>using namespace std;int n;int c[5005*4];int a[5005];inline int lowbit(int x){    return (x&-x);}void add(int x,int value){    for(int i=x;i<=n;i+=lowbit(i))     c[i]+=value;}int sum(int x) //找出x前面比x小的数的个数{    int sum=0;    for(int i=x;i;i-=lowbit(i))     sum+=c[i];    return sum;}int main(){   // freopen("q.txt","r",stdin);    while(scanf("%d",&n)==1)    {        int res=0;        memset(c,0,sizeof(c));        for(int i=1;i<=n;i++)        {            scanf("%d",&a[i]);            a[i]++;            // cout<<lowbit(a[i])<<"& ";            add(a[i],1);            res+=(i-sum(a[i]));        }        int mmin=5000000;        for(int i=1;i<=n;i++)        {            res=res-(a[i]-1)+(n-a[i]);            mmin=min(mmin,res);        }        cout<<mmin<<endl;    }}

其实。。。以前用过线段树,但总觉得自己没有领悟到本质。。~~~~(>_<)~~~~  还需要再认真思考啊,总是参照别人对的代码,当然很容易作对啊


0 0
原创粉丝点击