HDU1394 Minimum Inversion Number

来源:互联网 发布:大数据魔镜免费吗 编辑:程序博客网 时间:2024/05/24 23:13

一. 原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394

二. 题目大意:给一个数列,数列中的数由0到N-1(无序)。每次把数列的第一个数移动到最后一个。求这N个序列中逆序数最小的个数。逆序数就是说对于i<j,若a[i]>a[j],则形成一对逆序数。

三. 解题思路:据说暴力也可以过,只要求出初始的时候的逆序数,然后进行递推。下面介绍线段树解法和递推。

1. 线段树求出初始时的逆序数:在区间为[0,N-1]中,每次读入一个数ele,先查询[ele, N-1]这个区间中有多少个数,再进行单点更新。累积的数就是逆序数的和。时间复杂度O(nlgn)。

2. 递推方法:如果把一个数ele从第一个放到最后一个,比它小的数为ele个,比它大的为N-1-ele个,而这些数全部都在ele后面,因此若当前逆序数为cnt,那么把一个数ele从第一个放到最后一个之后,cnt = cnt-ele+N-1-ele。

四. 代码:

#include <cstdio>using namespace std;const int MAX_N = 5100,          INF = 0x3f3f3f3f;#define LC(t) t<<1#define RC(t) t<<1|1struct node{    int l, r, num;};node seTree[4*MAX_N];int arr[MAX_N];void build(int l, int r, int nd){    seTree[nd].l = l;    seTree[nd].r = r;    seTree[nd].num = 0;    if(l == r)        return;    int mid = l+r >>1;    build(l, mid, LC(nd));    build(mid+1, r, RC(nd));}void update(int ele, int nd){    int &l = seTree[nd].l,        &r = seTree[nd].r,        &num = seTree[nd].num;    if(ele == l && ele == r){        num++;        return;    }    if(ele < l || ele > r)        return;    int mid = l+r >>1;    if(ele <= mid)        update(ele, LC(nd));    else        update(ele, RC(nd));    num = seTree[LC(nd)].num + seTree[RC(nd)].num;}int query(int l, int r, int nd){    int &lSide = seTree[nd].l,        &rSide = seTree[nd].r,        &num = seTree[nd].num;    if(l == lSide && r == rSide)        return num;    if(r < lSide || l > rSide)        return 0;    int mid = lSide+rSide >>1;    if(r < mid)        return query(l, r, LC(nd));    if(l > mid)        return query(l, r, RC(nd));    return query(l, mid, LC(nd)) + query(mid+1, r, RC(nd));}int main(){    //freopen("in.txt", "r", stdin);    int N, i, j, cnt, res;    while(~scanf("%d", &N)){        build(0, N-1, 1);        cnt = 0;        for(i = 1; i <= N; i++){            scanf("%d", arr+i);            cnt += query(arr[i], N-1, 1);            update(arr[i], 1);        }        res = cnt;        for(i = 1; i <= N; i++){            cnt = cnt-arr[i]+N-arr[i]-1;            res = res>cnt? cnt:res;        }        printf("%d\n", res);    }    return 0;}


0 0
原创粉丝点击