概述
|
Minimum Inversion NumberTime Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 24293 Accepted Submission(s): 14387 Problem Description 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.
Input 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.
Output For each case, output the minimum inversion number on a single line.
Sample Input 10 1 3 6 9 0 8 5 7 4 2
Sample Output 16
Author CHEN, Gaoli
Source ZOJ Monthly, January 2003
Recommend Ignatius.L
先贴上别人解这道题的三种解法:https://blog.csdn.net/hnust_xiehonghao/article/details/8988809 首先得了解思路,只有知道了思路才有耐心看代码 这题看了我好久,百度了好多,因为根本就不知道思路,连暴力都看不懂,就是因为下面这个不懂 每次将新的序列的第一个y[i]移到最后,sum将减少a[i]个,当然同时还会增加n-1-a[i]; (a[i] 存的就是输入的数,以案例为例就是 1 3 6 9 0 8 5 7 4 2) 之后才发现它的输入的数是0,1,2,3,..,n-1这n个数(看来我读题不够仔细啊),这样就讲得通下面这个 把a[i]放到末尾时,比a[i]小的数的个数(low(a[i]) 就是a[i] ,比a[i]大的数的个数为n-1-a[i] 知道了思路就容易了,先贴上暴力代码(来自上面的链接) |
#include<stdio.h>
int a[5555];
int main()
{
int n,i,j,ans=999999999;
while(scanf("%d",&n)!=EOF)
{
ans=999999999;
for(i=0;i<n;i++) scanf("%d",&a[i]);
int cnt=0;
for(i=0;i<n;i++)
for(j=i+1;j<n;j++)
{
if(a[i]>a[j]) cnt++;
}
// printf("cnt=%dn",cnt);
if(ans>cnt) ans=cnt;
for(i=0;i<n;i++)
{
cnt=cnt-a[i]+n-1-a[i];
if(ans>cnt) ans=cnt;
}
printf("%dn",ans);
}
return 0;
}
对于线段树的代码可以自己根据这个主要思路打出代码
结合这个方法
下面的链接中我将线段树代码部分贴了出来,链接中的该部分有些小小滴错误
在链接中的注释的基础上,添加了一点自己理解的注释,可以先看看每个函数的作用(注释部分)
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <map>
using namespace std;
#define ll long long
const int maxn=5005;
struct Tree
{
int left,right;
int val;
}tree[maxn<<2];
int val[maxn];
void build(int l,int r,int root)
{
tree[root].left=l;
tree[root].right=r;
tree[root].val=0;
if(l==r) return ;
int mid=l+r>>1;
build(l,mid,root<<1);
build(mid+1,r,root<<1|1);
}
//查询已经插入的数中有多少个数比val[i]大
//即查询区间[val[i],n-1]中数的个数
int query(int l,int r,int root)
{
if(l==tree[root].left&&tree[root].right==r)
return tree[root].val;
int mid=tree[root].left+tree[root].right>>1;
if(r<=mid)
return query(l,r,root<<1);
else if(l>mid)
return query(l,r,root<<1|1);
else
return query(l,mid,root<<1)+query(mid+1,r,root<<1|1);
}
//更新所有包含id这个数的区间的val值,都+1
void update(int id,int root)
{
tree[root].val++;
if(tree[root].left==tree[root].right) return ;
int mid=tree[root].left+tree[root].right>>1;
if(id<=mid) update(id,root<<1);
else update(id,root<<1|1);
}
int main()
{
int i,n;
while(scanf("%d",&n)==1)
{
build(0,n-1,1);
int sum=0;
for(int i=0;i<n;i++)
{
scanf("%d",&val[i]);
sum+=query(val[i],n-1,1);
update(val[i],1);
}
int ret=sum;
for(int i=0;i<n;i++)
{
sum=sum-val[i]+(n-val[i]-1);
ret=min(ret,sum);
}
printf("%dn",ret);
}
return 0;
}
https://wenku.baidu.com/view/6e02b7492e3f5727a5e9623f.html(这里面讲得相当详细)
最后
以上就是飞快纸鹤为你收集整理的hdu 1394 解题报告 简单易懂Minimum Inversion Number的全部内容,希望文章能够帮你解决hdu 1394 解题报告 简单易懂Minimum Inversion Number所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复