HDU 1394 Minimum Inversion Number (线段树&&暴力)
2014-08-06 16:22
417 查看
Minimum Inversion Number
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 10477 Accepted Submission(s): 6464
[align=left]Problem Description[/align]
The inversion number of a given number sequence a1, a2, ..., an is the number of pairs (ai, aj) that satisfy i < j and ai > aj.
For a given sequence of numbers a1, a2, ..., an, if we move the first m >= 0 numbers to the end of the seqence, we will obtain another sequence. There are totally n such sequences as the following:
a1, a2, ..., an-1, an (where m = 0 - the initial seqence)
a2, a3, ..., an, a1 (where m = 1)
a3, a4, ..., an, a1, a2 (where m = 2)
...
an, a1, a2, ..., an-1 (where m = n-1)
You are asked to write a program to find the minimum inversion number out of the above sequences.
[align=left]Input[/align]
The input consists of a number of test cases. Each case consists of two lines: the first line contains a positive integer n (n <= 5000); the next line contains a permutation of the n integers from 0 to n-1.
[align=left]Output[/align]
For each case, output the minimum inversion number on a single line.
[align=left]Sample Input[/align]
10
1 3 6 9 0 8 5 7 4 2
[align=left]Sample Output[/align]
16
[align=left]Author[/align]
CHEN, Gaoli
[align=left]Source[/align]
ZOJ Monthly, January 2003
[align=left]Recommend[/align]
Ignatius.L
题目的意思就是说给你一个序列,求这个序列的逆序数的对数,然后将第一个元素放到最后,从而生成了一个新的序列,直到最后一个元素到第一个时停止,求生成的序列中,最少的逆序数的对数是多少。
我谈谈我的做法
1.暴力,每次找出新序列的逆序数的对数,然后看看是不是最小值,最后输出最小值即可
但这里要点技巧,在寻找新的序列的逆序数的对数时,没有必要去扫一遍出结果。
可以想想,因为序列的数字是从0~n-1连续的,那么当第一个数移到最后去的时候,原来比这个数大的数字变成了逆序数,比这个数小的数就不是逆序数了
举个例子:
3 2 4 5
本来 3 2是逆序数,3 4,3 5不是逆序数,当序列变成2 4 5 3时,原来的3 4变成了4 3是逆序数,2 3就不是逆序数了
所以在原有的序列中比第一个元素要小的数个数为(即逆序数的对数) low[a[i]]=a[i],所以可以推出比第一个元素要大的数的个数为up[a[i]]=n-1-a[i]
那么新的序列中逆序数的对数是 sum=sum-low[a[i]]+up[a[i]]=sum-a[i]+(n-1-a[i])
暴力的代码
#include<cstdio> #include<cstring> #include<stdlib.h> #include<algorithm> using namespace std; struct node { int l,r; int num; int mid() { return (l+r)>>1; } }a[5000*4]; int b[5005]; void btree(int l,int r,int step) { a[step].l=l; a[step].r=r; a[step].num=0; if(l==r) return ; int mid=a[step].mid(); btree(l,mid,step*2); btree(mid+1,r,step*2+1); } void ptree(int step,int vis) { a[step].num++; if(a[step].l==a[step].r) return ; int mid=a[step].mid(); if(vis>mid) ptree(step*2+1,vis); else ptree(step*2,vis); } int fintree(int step,int x,int y) { if(a[step].l==x&&a[step].r==y) return a[step].num; int mid=a[step].mid(); if(x>mid) return fintree(step*2+1,x,y); else if(y<=mid) return fintree(step*2,x,y); else return fintree(step*2,x,mid)+fintree(step*2+1,mid+1,y); } int main() { int n,i,j; while(scanf("%d",&n)!=EOF) { int ans=0; btree(0,n-1,1); for(i=0;i<n;i++) { scanf("%d",&b[i]); ans+=fintree(1,b[i],n-1); ptree(1,b[i]); } int minn=ans; for(i=0;i<n;i++) { ans=ans-b[i]+(n-1-b[i]); if(minn>ans) minn=ans; } printf("%d\n",minn); } return 0; }
View Code
相关文章推荐
- HDU 1394 Minimum Inversion Number【线段树&&归并排序】
- HDU1394 Minimum Inversion Number(线段树单点更新,暴力,逆序数)
- HDU 1394 Minimum Inversion Number(暴力/线段树)
- HDU 1394 Minimum Inversion Number( 归并排序 & 线段树 )
- hdu 1394 Minimum Inversion Number(暴力或线段树)
- Hdu 1394-Minimum Inversion Number【暴力求解Or线段树Or树状数组】
- HDU 1394 Minimum Inversion Number (暴力+线段树)
- HDU 1394 Minimum Inversion Number(最小逆序数/暴力 线段树 树状数组 归并排序)
- HDU ~ 1394 ~ Minimum Inversion Number(暴力||归并排序||线段树||树状数组)
- hdu 1394 Minimum Inversion Number 求逆序数(树状数组/归并排序/暴力)
- HDU 1394 Minimum Inversion Number(循环数组求逆序数)(暴力,归并排序,线段树)
- Minimum Inversion Number(hdu1394(线段数or暴力))
- hdu 1394 Minimum Inversion Number(最小逆序数) 线段树/暴力
- HDU 1394 &amp; ZOJ 1484 Minimum Inversion Number
- [hdu]1394 Minimum Inversion Number -- 暴力求逆序、树状数组求逆序、线段树求逆序、归并排序求逆序
- hdu 1394 Minimum Inversion Number (裸树状数组 求逆序数 && 归并排序求逆序数)
- [逆序对] 入门 — [HDU] 1394 - Minimum Inversion Number & [HDU] 4911 - Inversion
- HDU 1394 Minimum Inversion Number (最小逆序对数&线段树)
- HDU 1394 & ZOJ 1484 Minimum Inversion Number
- HDU 1394 Minimum Inversion Number