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

题目大意:逆序数:即假设在数组a中,假如i<j,但是a[i]>a[j]。

现在有一个数组,含有n个数(为0-(n-1)的一个排列),依次把第一个数,放到数组最后面,求其中逆序数数目最小是多少?

例:

Sample Input
10 1 3 6 9 0 8 5 7 4 2
 
Sample Output
16

解题思路:首先,我们要思考对于一个数组怎样求出它的逆序数的总个数,这里有两种方法,最简单的是,直接暴力,两层循环就可以搞定。这里主要讲一下第二种方法,用线段树也可以很巧妙的求它的逆序数个数,我们先建立一颗空树,然后一个一个将节点插入树中,我们把数组中数的大小看成在树中的位置,然后每插入一个节点,就统计大于这个数的数目,即产生的逆序数的数目,然后再更新该位置的数值为1.这样就求出了初始状态下的逆序数sum了。

然后要求出最小的逆序数,因为数组是0到n-1的一个排列,所以如果当你把第一个数从第一个放到最后一个的时候,逆序数就会减少a【i】个,同时增加n-(a[i]+1)个。所以我们只需要枚举依次把第一个数放到最后位置,所产生的逆序数sum+(n-2*num[i]-1)取最小值即可。

附上代码:

暴力解法:

#include<iostream>
using namespace std;
#define inf 0x3f3f3f3f
int n,a[]; int main()
{
while(~scanf("%d",&n))
{
for(int i=;i<=n;i++)
scanf("%d",&a[i]);
int sum=;
for(int i=;i<=n;i++)
{
for(int j=i+;j<=n;j++)
{
if(a[i]>a[j])
sum++;
}
}
int ans=inf;
for(int i=;i<=n;i++)
{
sum+=(n-*a[i]-);
ans=min(ans,sum);
}
printf("%d\n",ans);
}
return ;
}

线段树解法:

#include<iostream>
#include<cstring>
using namespace std;
#define ll long long
#define maxn 10005
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define pushup() tree[root]=tree[root<<1]+tree[root<<1|1]
int n,tree[maxn<<],num[maxn<<]; /*
void pushdown(int l,int r,int root)
{
if(add[root])
{
add[root<<1]+=add[root];
add[root<<1|1]+=add[root];
tree[root<<1]+=l*add[root];
tree[root<<1|1]+=r*add[root];
add[root]=0;
}
}
void build(int l,int r,int root)
{
add[root]=0;
if(l==r)
{
tree[root]=num[tot++];
return;
}
int mid=l+r>>1;
build(lson);
build(rson);
pushup();
}*/
void update(int pos,int val,int l,int r,int root)
{
if(l==r)
{
tree[root]=val;
return;
}
int mid=l+r>>;
if(pos<=mid)
update(pos,val,lson);
else
update(pos,val,rson);
pushup();
}
int query(int L,int R,int l,int r,int root)
{
if(L<=l&&R>=r)
return tree[root];
int ans=,mid=l+r>>;
if(L<=mid)
ans+=query(L,R,lson);
if(R>mid)
ans+=query(L,R,rson);
return ans;
} int main()
{
while(~scanf("%d",&n))
{
memset(tree,,sizeof(tree));//初始时,为空树,直接memset
int sum=;
for(int i=;i<=n;i++)
{
scanf("%d",&num[i]);
sum+=query(num[i]+,n,,n,);
update(num[i]+,,,n,);
}
int ans=sum;
for(int i=;i<=n;i++)
{
sum+=(n-*num[i]-);
ans=min(ans,sum);
}
printf("%d\n",ans);
}
return ;
}

hdu1394逆序数(线段树)的更多相关文章

  1. HDU 1394 Minimum Inversion Number(最小逆序数 线段树)

    Minimum Inversion Number [题目链接]Minimum Inversion Number [题目类型]最小逆序数 线段树 &题意: 求一个数列经过n次变换得到的数列其中的 ...

  2. HDU 1394 逆序数 线段树单点跟新 | 暴力

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

  3. 51Nod 1019 逆序数(线段树)

    题目链接:逆序数 模板题. #include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a) ...

  4. POJ 2299 Ultra-QuickSort 求逆序数 线段树或树状数组 离散化

    我用的线段树写的. num数组表示已插入的数值的个数. 由于a[i]数值很大,但是n不是很大,所以要离散化处理 9 1 0 5 4 离散化后 4 1 0 3 2 这样保证最大值不会超过n #inclu ...

  5. hdu1394 分治 or 线段树

    利用分治求一次逆序数,然后每次把第一个元素放到末尾,设该交换元素的值为x,设上一次求得的逆序数为y,那么此时的逆序数等于y - x + (n - x - 1),减去x是因为x作为第一个元素,其后共有x ...

  6. 逆序对 线段树&树状数组 (重制版)

    逆序对的定义:长度为n的数组a,求满足i<j时a[i]>a[j]条件的数对个数. 第一次接触这种问题的人可能是更先想到的是n^2去暴力数前面有几个比他大的数. int main() { i ...

  7. 51nod1019逆序数(归并排序/树状数组)

    题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1019 题意:中文题诶- 思路: 方法1:归并排序- 归并排序过 ...

  8. 2019.01.22 bzoj3333: 排队计划(逆序对+线段树)

    传送门 题意简述:给出一个序列,支持把ppp~nnn中所有小于等于apa_pap​的'扯出来排序之后再放回去,要求动态维护全局逆序对. 思路:我们令fif_ifi​表示第iii个位置之后比它大的数的个 ...

  9. CF #301 E:Infinite Inversions(逆序数,树状数组)

    A-Combination Lock  B-School Marks   C-Ice Cave   D-Bad Luck Island   E-Infinite Inversions E:Infini ...

随机推荐

  1. Es6数值拓展

    Es6数值拓展 一,Number扩展 1,ES6 提供了二进制和八进制数值的新的写法,分别用前缀0b(或0B)和0o(或0O)表示. 将0b和0o前缀的字符串数值转为十进制,要使用Number方法 N ...

  2. javax.validation.ValidationException: Unable to create a Configuration, because no Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.

    项目依赖 <dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifa ...

  3. jQuery的each使用陷阱

    注意:jQuery使用each()函数进行循环时发现return false不能阻止程序继续向下执行 原因如下: (1)开始还以为是jQuery的each()函数是异步执行的,所以导致出错,其实不是. ...

  4. python数据结构与算法第八天【冒泡排序】

    1.排序算法的稳定性 稳定排序算法会让原本有相同键值的记录维持相对次序 例如:对以下元组按照元组的第一个元素升序排列,元组如下: (4,1) (3,1) (3,7) (5,6) 若要满足条件,则可能的 ...

  5. dbExpress操作中用TDBGrid显示数据

    由于一些数据感知组件如TDBGrid等是需要用到数据缓存的,这和dbExpress组件的存取机制是矛盾的.所以当打开数据集时会出现如下内容的警告框:“Operation not allowed on ...

  6. Docker 部署应用、jar 工程 docker 方式部署

    https://blog.csdn.net/jiangyu1013/article/details/81988342

  7. Nginx 当上游服务器返回失败时的处理办法

    陶辉95课 Syntax: proxy_next_upstream error | timeout | invalid_header | http_500 | http_502 | http_503  ...

  8. python时间模块datetime

    datetime模块 datetime在python中比较常用,主要用来处理时间日期,使用前先倒入datetime模块.下面总结下本人想到的几个常用功能. 1.当前时间(日期.小时.字符串时....) ...

  9. RPM包定制

    概述 问题:当领导给你 100 台已经安装好系统的服务器,然后让优化,让你提出一个快速部署方案.解答: 1.tar 打包 先编译安装 打包-->分发-->解包(比如 mysql 打包后直接 ...

  10. python的if not用法

    python里的if not的用法: None,False,0,空列表[],空字典{},空元祖(),都相当于false print('not x 打印出来的结果',not x) x =[1] prin ...