zoukankan      html  css  js  c++  java
  • hdu 13394 Minimum Inversion Number 线段树

    题意:

    首先给你一个长度为n的序列v,你需要首先找出来逆序对(i<j && v[i]>v[j])

    然后把这个序列的最后一个元素放在第一个位置上,其他元素都向后移动一位。

    一直这样操作,会得到n个序列,问你这n个序列中,哪个序列中的逆序对数最少,并输出

    题解:

    首先我们可以通过线段树得到最初哪个序列的逆序对数,其实也可以通过归并排序得到,因为我是练习线段树,所以用的线段树写的

    线段树求逆序对数的话,我们可以求出来v[i]可以和v[j]形成的逆序对数,这个j的取值范围为1<=j<i,我们可以维护一个最小值,然后得到有多少j能和v[i]构成逆序对

    这一点不懂可以看一下代码

    对于其他序列,你会发现就只是把最后一个元素放在第一个位置上,其他元素都向后移动一位。

    那么原来上一个序列的逆序对数会减少n-v[n],因为对于v[n]元素,它是最后一个元素,那么肯定v[n]+1,v[n]+2...n都可以和v[n]构成逆序对

    逆序对数会增加v[n]-1个,因为v[n]移动到第一个位置之后,那么1,2,3...v[n]-1都可以和v[n]构成一个逆序对数

    代码:

    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxn=2e5+10;
    const int INF=0x3f3f3f3f;
    #define ll long long
    #define mem(a) memset(a,0,sizeof(a))
    #define mem_(a) memset(a,-1,sizeof(a))
    #define mem__(a) memset(a,INF,sizeof(a))
    int lazy[maxn<<2],tree[maxn<<2],arr[maxn];
    void push_up(int root)
    {
        tree[root]=min(tree[root<<1],tree[root<<1|1]);
    }
    void build(int root,int L,int R)
    {
        if(L==R)
        {
            tree[root]=arr[L];
            return;
        }
        int mid=(L+R)>>1;
        build(root<<1,L,mid);
        build(root<<1|1,mid+1,R);
        push_up(root);
    }
    void update(int root,int L,int R,int pos,int val)
    {
        if(L==R)
        {
            tree[root]=val;
            return;
        }
        int mid=(L+R)>>1;
        if(pos<=mid)
            update(root<<1,L,mid,pos,val);
        else update(root<<1|1,mid+1,R,pos,val);
        push_up(root);
    }
    int query(int root,int L,int R,int LL,int RR,int val)
    {
        if(LL<=L && R<=RR)
        {
            if(tree[root]>val)
            {
                return R-L+1;
            }
            if(L==R) return 0;
        }
        int mid=(L+R)>>1,ans=0;
        if(LL<=mid) ans+=query(root<<1,L,mid,LL,RR,val);
        if(RR>mid) ans+=query(root<<1|1,mid+1,R,LL,RR,val);
        return ans;
    }
    int main()
    {
        int n;
        while(~scanf("%d",&n))
        {
            int sum=0;
            mem__(tree);
            //update(1,1,n,1,2);
            //printf("%d**
    ",query(1,1,n,1,1,1));
            for(int i=1;i<=n;++i)
            {
                //int x;
                scanf("%d",&arr[i]);
                if(i!=1)
                {
                    sum+=query(1,1,n,1,i-1,arr[i]);
                }
                update(1,1,n,i,arr[i]);
                arr[i]+=1;
            }
            int minn=sum;
            //printf("%d***
    ",sum);
            for(int i=n;i>1;--i)
            {
                sum=sum+((arr[i]-1)-(n-arr[i]));
                minn=min(sum,minn);
            }
            printf("%d
    ",minn);
        }
        return 0;
    }
  • 相关阅读:
    ApacheCN JavaScript 译文集 20211122 更新
    ApacheCN jQuery 译文集 20211121 更新
    ApacheCN 大数据译文集(二) 20211206 更新
    我这里一直空荡荡的,还占着博客园的位置,真是不好意思
    2009年最后一天
    学习petshop的朋友。这里有一些讲坐下载
    Repeater控件中如何做编辑和删除功能
    可以让你少奋斗十年的工作经验
    GridView自定义分页,模仿GridView的自动分页功能
    从内容面访问母版页中的控件或属性
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/13709382.html
Copyright © 2011-2022 走看看