title: 线段树-最小逆序数

date: 2018-10-12 17:19:16

tags:

  • acm
  • 算法
  • 刷题

    categories:
  • ACM-线段树

概述

这是一道简单的线段树的题,,,当然还有很多其他的做法,,,甚至时暴力都可以,,,

用线段树主要是为了在练一练线段树的使用,,,而且这次,,我换了一种写线段树的方法,,,

貌似也是很多大佬都在用的一种写法,,,

之前一直用的入门时为了好理解的一种写法:节点用结构体node表示,,,并且为了理解还添了每一个节点所对应的左右边界,,,

但实际上,,这些信息是没有用的,,,或者说是多余的,,,直接在使用时计算或者直接作为函数的形参传递就行了,,,,

这样的写法代码量更加的少而写写起来也方便,,,占用的空间也少了些,,,

题目的分析

这道题不像之前做的线段树的题那样所维护的值就是最终要求的答案,,,而是中间的某一过程量,,,

首先,,题目的意思就是对于一个给定的数列 \(a_0 , a_1 , a_2 , ,,, ,a_{n-1}\),,,每次将第一个数移动到后面,,,这样一共有n种序列,,,然后对于每一种序列都有一个 逆序数 ,,问你在这些逆序数中最小的那个是多小,,,,

  • 这道题只要知道其中一个序列的逆序数,,它的相邻一个逆序数也就可以推出来,,,具体是这样的:

    \(当已知第i个序列的逆序数sum_i时,,\)

    \(第i+1个序列的逆序数为sum_{i+1}=sum_i + n - a[i] - 1 - a[i],,,,\)

    \(就是说当将第一个数移到最后前,,,\)

    \(它以前的逆序数有 a[i] 个所以要减去这些,,\)

    \(而当它被移到最后时,,,\)

    \(前面又多了 n - a[i] - 1 个,,,\)

    \(最后的sum就求出来了,,,\)

  • 当知道上面这个递推式后,,,我们的任务就是求出所输入出的数列的逆序数,,,然后再根据递推式找出最小的那一个输出就行了,,,

  • 对于求这个数列的逆序数用线段树的方法是,,,先建一个空的数,,,然后每输入一个数,,标记一下,,不过标记在最后的更新完成,,,先求出它之前所输入的所有数中比它大的数(也就是看这个数到n-1一共有几个出现在之前的输入中,,,也就是看标记的和),,,也就是以它构成的逆序列,,,然后把它加(标记)到这个树里(更新),,,可以看出如果把标记改为存放这个数,,纳闷这棵树的叶子节点就是排序好的1~n-1数列,,,,这一段画个图就好理解了,,,

实现

code:

#include <iostream>
#include <cstdio>
#include <cstdlib> using namespace std; #define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r const int maxn = 5005;
int sum[maxn << 2]; void pushup(int rt)
{
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}
void build(int rt , int l , int r)
{
sum[rt] = 0;
if(l == r)
return; int mid = (l + r) >> 1; build(lson);
build(rson);
pushup(rt);
}
void update(int rt , int l , int r , int loc)
{
if(l == r)
{
++sum[rt];
return;
} int mid = (l + r) >> 1;
if(loc <= mid) update(lson , loc);
else update(rson , loc);
pushup(rt);
}
int query(int rt , int l , int r , int L , int R)
{
if(L <= l && r <= R)
return sum[rt]; int mid = (l + r) >> 1; int ans = 0;
if(L <= mid) ans += query(lson , L , R);
if(R > mid) ans += query(rson , L , R);
return ans;
}
int a[maxn];
int main()
{
int n;
while(scanf("%d" , &n) != EOF)
{
build(1 , 0 , n); int sm = 0;
for(int i = 0; i < n; ++i)
{
scanf("%d" , &a[i]);
sm += query(1 , 0 , n - 1 , a[i] , n - 1);
update(1 , 0 , n - 1 , a[i]);
} int ret = sm;
for(int i = 0; i < n; ++i)
{
sm += n - a[i] - 1 - a[i];
ret = min(sm , ret);
}
printf("%d\n" , ret);
}
}

线段树-最小逆序数hdu1394的更多相关文章

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

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

  2. HDU_1394_Minimum Inversion Number_线段树求逆序数

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

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

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

  4. 【线段树求逆序数】【HDU1394】Minimum Inversion Number

    题目大意: 随机给你全排列中的一个,但不断的把第一个数丢到最后去,重复N次,形成了N个排列,问你这N个排列中逆序数最小为多少 做法: 逆序数裸的是N^2 利用线段树可以降到NlogN 具体方法是插入一 ...

  5. 线段树求逆序数方法 HDU1394&amp;&amp;POJ2299

    为什么线段树能够求逆序数? 给一个简单的序列 9 5 3 他的逆序数是3 首先要求一个逆序数有两种方式:能够从头開始往后找比当前元素小的值,也能够从后往前找比当前元素大的值,有几个逆序数就是几. 线段 ...

  6. hdu1394 Minimum Inversion Number (线段树求逆序数&&思维)

    题目传送门 Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K ...

  7. HDU-1394 Minimum Inversion Number(线段树求逆序数)

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

  8. HDU - 1394 Minimum Inversion Number (线段树求逆序数)

    Description The inversion number of a given number sequence a1, a2, ..., an is the number of pairs ( ...

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

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

随机推荐

  1. centos无法通过ssh连接的解决

    系统环境是centos7,虚拟机环境下的.在使用ssh工具连接虚拟机的时候发现连接不上,用的是root 先检查openssh-server是否安装: yum list installed | grep ...

  2. Jekens Source Code Management None 源码管理没有Git

    jekens安装完成后,在配置中Source Code Management没有Git的选项,只有none,搞了大半天,一直安装插件报错,网上找的各种文章均未能解决我的问题,多次尝试后终于解决了这个问 ...

  3. Linux基础-free窥内存-dd探硬盘

    监控内存篇(RAM)-free free指令可以很直观的看到内存的使用情况 free -m指令以单位为MB的方式查看内存的使用情况(free命令读取的文件是/proc/meminfo) 这个表格的解释 ...

  4. php strcmp()函数

    <? $str = "LAMP"; $str1 = "LAMPBrother"; $strc = strcmp($str,$str1); switch ( ...

  5. 容斥原理&&莫比乌斯专题

    A题:A - Eddy's爱好   HDU - 2204 具体思路:如果是求n中,为平方数的有多少个,那么答案肯定是sqrt(n),同理,如果是三次根号的话,那么答案肯定是n的三分之一次方.然后继续按 ...

  6. 基于Ubuntu搭建GMS测试环境

    一.版本信息: 系统版本:Ubuntu 18.04.2 LTS JDK版本: 1.8.0_171 SDK版本:android-sdk_r24.4.1-linux.tgz ADB版本:1.0.40 ap ...

  7. windows 下安装mysqlclient 包

    正常情况下是可以直接用 pip install mysqlclient 进行安装的.如果你的机器上安装的既有python3 又有python2.7 的话,建议使用python -m pip insta ...

  8. 弹性盒模型justify-content属性

    justify-content是应用于父容器上来规定子元素在水平方向上的对齐方式的. flex-start 左对齐 flex-end 右对齐 center 居中 space-betten 两端对齐,两 ...

  9. Java IO,硬骨头也能变软

    开胃菜 先看一张网上流传的http://java.io包的类结构图: 当你看到这幅图的时候,我相信,你跟我一样内心是崩溃的. 有些人不怕枯燥,不怕寂寞,硬着头皮看源码,但是,能坚持下去全部看完的又有几 ...

  10. j-linkV8固件更新(任意版本)

    在使用j-link v8调试程序时,容易出现固件丢失或出错的情况,导致电脑不能识别,j-link上面的灯不亮.我今天刚刚遇到了这个情况,于是就拆开外壳,在网上搜索资料,发现刷固件相关的还真多,但是有一 ...