zoukankan      html  css  js  c++  java
  • hdu 1394 (线段树求逆序数)

    <题目链接>

    题意描述:

    给你一个有0--n-1数字组成的序列,然后进行这样的操作,每次将最前面一个元素放到最后面去会得到一个序列,那么这样就形成了n个序列,那么每个序列都有一个逆序数,找出其中最小的一个输出!

    解题分析:

    先利用线段树求出初始序列的逆序数,这里有一个非常巧妙的地方,由于比a[i]大的数是离散且连续的,所以可以用线段树来实现(与线段树节点的区间特性符合)。

    #include <bits/stdc++.h>
    using namespace std;
    
    #define Lson rt<<1,l,mid
    #define Rson rt<<1|1,mid+1,r
    const int N = 5e3+5;
    int n;
    int tr[N<<2],arr[N];
    inline void Pushup(int rt){ tr[rt]=tr[rt<<1]+tr[rt<<1|1]; }
    void update(int rt,int l,int r,int loc){
        if(l==r){ tr[rt]+=1;return; }     //将这个点插入线段树
        int mid=l+r>>1;
        if(loc<=mid)update(Lson,loc);
        if(loc>mid)update(Rson,loc);
        Pushup(rt);
    }
    int query(int rt,int l,int r,int L,int R){
        if(L<=l && r<=R){ return tr[rt]; }
        int mid=l+r>>1;
        int ans=0;
        if(L<=mid)ans+=query(Lson,L,R);
        if(R>mid)ans+=query(Rson,L,R);
        return ans;
    }
    int main(){
        while(~scanf("%d",&n)){
            memset(tr,0,sizeof(tr));
            int sum=0;
            for(int i=1;i<=n;i++){
                scanf("%d",&arr[i]);
                sum+=query(1,0,n-1,arr[i]+1,n-1);     //逆序数之前插入的,比这个数要大的数的个数
                update(1,0,n-1,arr[i]);
            }
            //此时ans为原序列的逆序数
            int ans=sum;
            for(int i=1;i<=n-1;i++){        //只用重新算n-1次就行,因为第n次与原序列相同 
                sum+=(n-1-2*arr[i]);        //注意这里求逆序数,必须是在前一个序列的基础上求 
                ans=min(ans,sum);
            }
            printf("%d
    ",ans);
        }
    }
  • 相关阅读:
    Core Location定位
    iOS中的round/ceil/floorf函数略解
    NSDateFormatter相关整理
    iOS使用NSMutableAttributedString 实现富文本(不同颜色字体、下划线等)
    自定义带DropDownTable的TextField(事件)
    自定义带DropDownTable的TextField(UI部分)
    读取json文件内容
    在UITextview中添加链接属性的文字
    自定义弹出框Alter
    给UIView加上点击事件
  • 原文地址:https://www.cnblogs.com/00isok/p/9351602.html
Copyright © 2011-2022 走看看