题目链接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. [转帖]一键获取 所有连接过的wifi 密码

    cmd 一键获取 所有连接过的wifi 密码 转帖来源: http://www.cnblogs.com/hookjoy/p/5537623.html for /f "skip=9 token ...

  2. MyBaits全局配置文件的各项标签1

    ■dtd约束     <!DOCTYPE configuration           PUBLIC "-//mybatis.org//DTD Config 3.0//EN" ...

  3. flutter开发vscode用模拟器调试

    android studio的太重,我装的是android sdk,使用avd的模拟器启动黑屏 启动夜神模拟器(已卸载) 建立连接: adb connect 127.0.0.1:62001    (夜 ...

  4. 简单易懂的softmax交叉熵损失函数求导

    参考: https://blog.csdn.net/qian99/article/details/78046329

  5. python爬虫scrapy的LinkExtractor

    使用背景: 我们通常在爬去某个网站的时候都是爬去每个标签下的某些内容,往往一个网站的主页后面会包含很多物品或者信息的详细的内容,我们只提取某个大标签下的某些内容的话,会显的效率较低,大部分网站的都是按 ...

  6. CentOS7下Nginx搭建反向代理,并使用redis保存session

    1.启动两个tomcat,端口分别为8080,8081 2.配置nginx,vim /usr/local/nginx/conf/nginx.conf 添加如下配置: 3.启动nginx或热加载 启动: ...

  7. python设计模式第二十五天【访问者模式】

    1.应用场景 (1)将数据和行为进行分离,不同的角色具有不同的行为 2.代码实现

  8. adoquery怎样判断数据在缓存中有修改啊

    ADOQry.Filtered:=false;       ADOQry.Filtered:=true;       ADOQry.FilterGroup:=fgPendingRecords ;Fil ...

  9. 获取DataSet中某行某列的数据

    LabelText = DataSet11.Tables("COMM.USERS").Rows[0]["User_Name"].tostring() Label ...

  10. js正則表達式

    正則表達式實例化的兩種方式: 字符型 var a=// 對象型var a=new RegExp(,) 修飾符: i:忽略大小寫 g:全局搜索 m:多行搜索 元字符: \轉義字符 \w:字符,數字,下劃 ...