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

题目大意:

给出一个序列,一对逆序数就是满足i<j&&a[i]>a[j]条件的一对数字。

每次将a数组的最后一个数放到数组的第一位上,原数组向后移动一位,得到一个新的序列,

求这些序列中最小的逆序数。(每个数都在0-n-1范围内)

求解思路:

(1)逆序数的性质:一个序列第i次循环的逆序数Pi=P(i-1)+(n-1-a[i])-a[i]。

(2)可以通过暴力求解,每次找最小值就行了。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = ;
const int INF = ;
int a[maxn];
int main(void)
{
int mi,cnt,i,j,num,n;
while(~scanf("%d",&n))
{
memset(a,,sizeof(a));
for(i=;i<n;i++) scanf("%d",&a[i]);
mi=INF;cnt=;
for(i=;i<n;i++)
for(j=i+;j<n;j++)
if(a[i]>a[j]) cnt++;
if(mi>cnt) mi=cnt;
for(i=;i<n;i++)
{
cnt=cnt+(n--a[i])-a[i];
if(mi>cnt) mi=cnt;
}
printf("%d\n",mi);
}
return ;
}

(3)线段树做法:

先初始化线段树都为0,然后输入每个数,每个数字+1,即改为1-n区间,判断b[i]+1到n区间内有无数字,有的话逆序数就+1

然后再更新节点b[i]表示这个节点被访问过了。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = ;
const int INF = ;
int a[maxn<<],b[maxn];
void pushup(int x)
{
a[x]=a[x*]+a[x*+];
}
void build(int x,int l,int r)
{
if(l==r)
{
a[x]=;return ;
}
int mid=(l+r)/;
build(x*,l,mid);
build(x*+,mid+,r);
pushup(x);
}
void update(int x,int l,int r,int pos)
{
if(l==r)
{
a[x]++;return ;
}
int mid=(l+r)/;
if(pos<=mid) update(x*,l,mid,pos);
if(pos>mid) update(x*+,mid+,r,pos);
pushup(x);
}
int query(int x,int l,int r,int A,int B)
{
if(A<=l&&r<=B) return a[x];
int mid=(l+r)/,ans=;
if(A<=mid) ans+=query(x*,l,mid,A,B);
if(B>mid) ans+=query(x*+,mid+,r,A,B);
return ans;
}
int main(void)
{
int n,i,ans,mi;
while(~scanf("%d",&n))
{
memset(a,,sizeof(a));
memset(b,,sizeof(b));
build(,,n);
ans=;mi=INF;
for(i=;i<=n;i++)
{
scanf("%d",&b[i]);
b[i]++;
ans+=query(,,n,b[i]+,n);
update(,,n,b[i]);
}
if(mi>ans) mi=ans;
for(i=;i<n;i++)
{
ans=ans+(n-b[i]+)-b[i];
if(mi>ans) mi=ans;
}
printf("%d\n",mi);
}
return ;
}

(4)归并排序做法

归并排序时,当a[j]>a[i]时,每次记录tmp+=(mid-i+1),最终求出的tmp就是这个序列的逆序数。

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn = ;
int a[maxn],b[maxn],temp[maxn],tmp;
void Merge_Sort(int l,int r,int mid)
{
int pos=,i=l,j=mid+;
while(i<=mid&&j<=r)
{
if(a[i]>a[j]) tmp+=(mid+-i),temp[pos++]=a[j++];
else temp[pos++]=a[i++];
}
while(i<=mid) temp[pos++]=a[i++];
while(j<=r) temp[pos++]=a[j++];
for(i=;i<pos;i++) a[i+l]=temp[i];
}
void Merge(int l,int r)
{
if(l==r) return ;
int mid=(l+r)/;
Merge(l,mid);
Merge(mid+,r);
Merge_Sort(l,r,mid);
}
int main(void)
{
int n,ans,i;
while(~scanf("%d",&n))
{
for(i=;i<n;i++)
{
scanf("%d",&a[i]);b[i]=a[i];
}
tmp=;ans=;
Merge(,n-);
ans=tmp;
for(i=;i<n;i++){
tmp=tmp+n--b[i]*;
if(ans>tmp) ans=tmp;
}
printf("%d\n",ans);
}
return ;
}

hdu-1394(线段树&逆序数的性质和求法)的更多相关文章

  1. hdu 1394(线段树) 最小逆序数

    http://acm.hdu.edu.cn/showproblem.php?pid=1394 给出一列数组,数组里的数都是从0到n-1的,在依次把第一个数放到最后一位的过程中求最小的逆序数 线段树的应 ...

  2. hdu 1394 (线段树求逆序数)

    <题目链接> 题意描述: 给你一个有0--n-1数字组成的序列,然后进行这样的操作,每次将最前面一个元素放到最后面去会得到一个序列,那么这样就形成了n个序列,那么每个序列都有一个逆序数,找 ...

  3. hdu 1394 线段树计算逆序数

    线段树计算逆序数的原理: 用线段树来统计已插入的数的个数(所以要保证最大的那个数不能太大,否则数组都开不了),然后每插入一个数,就查询比插入的数大的个数,累加即可. 这个题还有一个特点就是,题目给的是 ...

  4. HDU 1394 线段树求逆序对

    Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java ...

  5. HDU 1394 线段树or 树状数组~

    Minimum Inversion Number Description The inversion number of a given number sequence a1, a2, ..., an ...

  6. hdu 1394 线段树

    Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java ...

  7. hdu 5877 线段树(2016 ACM/ICPC Asia Regional Dalian Online)

    Weak Pair Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total ...

  8. hdu 3974 线段树 将树弄到区间上

    Assign the task Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  9. hdu 3436 线段树 一顿操作

    Queue-jumpers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) To ...

随机推荐

  1. ES3之变量提升 ( hoisting )

    JavaScript引擎在预编译时,会将声明(函数声明.变量声明)自动提升至函数或全局代码的顶部.但是赋值不会提升. Because variable declarations (and declar ...

  2. Chrome控制台格式化输出

    一 格式化输出文字 console.log('%c你好','color:green;'); console.log('%c你好%c啊','color:green;','color:blue;'); 二 ...

  3. 利用crontab每天定时备份MySQL数据库

    当数据库服务器建立并正式投入生产使用后,我们不得不担忧一个问题:当数据库遭到破坏后,怎样安然恢复到最后一次正常的状态,使得数据的损失达到最小. 我这里以本博客的wordpress数据为例,来讨论并实现 ...

  4. sql case 与 sum

    <select id="selectTotal" resultType="java.util.Map" parameterType="java. ...

  5. FortiGate设备管理

    1.Web管理 1.FortiGate出厂配置 默认地址为192.168.1.99,可以通过https的方式进行web管理(默认用户名admin,密码为空).不同型号设备用于管理的接口略有不同,如: ...

  6. 整合使用持久层框架mybatis 使用SqlSessionTemplate模板类与使用映射接口 对比

    spring中整合使用mybatis的用法总结 一:在Spring配置Mybatis 第一步:将mybatis-spring类包添加 到项目的类库中 第二步:编写spring和持久层衔接的xml文件, ...

  7. jQuery的鼠标悬停时放大图片的效果

    这是一个基于jQuery的效果,当鼠标在小图片上悬停时,会弹出一个大图,该大图会跟随鼠标的移动而移动.这个效果最初源于小敏同志的一个想法,刚开始做的时候只能实现弹出的图片是固定的,不能随鼠标移动,最后 ...

  8. Java开发MIS系统需要的技术及其作用

    1.后台框架部分,常用spring.struts2(Struts2框架,提供了一种基于MVC体系结构的工程序的开发方法,具有组件模块化.灵活性和重用性等优点,使基于MVC模式的程序结构更加清晰,同时也 ...

  9. 织梦文章里面的图片alt和title属性,用文章标题自动替换

    把{dede:field.body/}改成{dede:field.body runphp=yes}global $dsql,$id,$aid;$myid = isset($id) ? $id : $a ...

  10. 解决 win 7 64 位 vs2010 调试silverlight项目无法加载,提示更新developer ,跟新报 消息 ID: 1517 已安装了 Silverlight 的 64 位版本

    出现上面的问题是我们安装的silverlight的版本和系统给的silverlight下载的版本冲突, 解决的方法是,首先卸载Silverlight runtime(也就是默认的silverlight ...