题意:给定一个序列,求分别将前m个数移到序列最后所得到的序列中,最小的逆序数。

分析:m范围为1~n,可得n个序列,求n个序列中最小的逆序数。

1、将序列从头到尾扫一遍,用query求每个数字之前有多少个大于该数字的数,方法如下。

(1)将已经扫过的数字所对应的位置标记,通过query求该数字之后有多少个数被标记过

(2)该数字之后所有被标记的数字,都是在该数字之前出现过的(i<j),而这些数字又大于该数字(ai>aj),因此该数字之后所有的标记和就是该数字之前比该数字大的数的个数。

2、sum为初始序列的逆序和,从前往后依次将每个数字移到序列最后。

假设当前把a[i]移到序列最后,则

后一个序列B的逆序和=前一个序列A的逆序和 - a[i] + (n - 1 - a[i])。

eg:假设前一个序列A为3 6 9 0 8 5 7 4 2 1,则a[i]为3。

a[i]是序列A的第一个数,a[i]后面的数中有a[i]个数小于a[i](分别为0,2,1),因此把a[i]移到最后,会减少a[i]个逆序数。

而a[i]后面的数中有 (n - 1 - a[i])个数大于a[i],因此把a[i]移到最后,会增加 (n - 1 - a[i])个逆序数。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<iostream>
#include<sstream>
#include<iterator>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#define lowbit(x) (x & (-x))
const double eps = 1e-8;
inline int dcmp(double a, double b){
if(fabs(a - b) < eps) return 0;
return a > b ? 1 : -1;
}
typedef long long LL;
typedef unsigned long long ULL;
const int INT_INF = 0x3f3f3f3f;
const int INT_M_INF = 0x7f7f7f7f;
const LL LL_INF = 0x3f3f3f3f3f3f3f3f;
const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f;
const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1};
const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1};
const int MOD = 1e9 + 7;
const double pi = acos(-1.0);
const int MAXN = 5000 + 10;
const int MAXT = 10000 + 10;
using namespace std;
int a[MAXN];
int cnt[MAXN << 2];
void update(int k, int id, int L, int R){
if(L == R){
++cnt[id];
}
else{
int mid = L + (R - L) / 2;
if(k <= mid) update(k, id << 1, L, mid);
else update(k, id << 1 | 1, mid + 1, R);
cnt[id] = cnt[id << 1] + cnt[id << 1 | 1];
}
}
int query(int l, int r, int id, int L, int R){
if(l <= L && R <= r){
return cnt[id];
}
int mid = L + (R - L) / 2;
int ans = 0;
if(l <= mid) ans += query(l, r, id << 1, L, mid);
if(r > mid) ans += query(l, r, id << 1 | 1, mid + 1, R);
return ans;
}
int main(){
int n;
while(scanf("%d", &n) == 1){
memset(cnt, 0, sizeof cnt);
int sum = 0;
for(int i = 0; i < n; ++i){
scanf("%d", &a[i]);
sum += query(a[i] + 1, n, 1, 1, n);
update(a[i] + 1, 1, 1, n);
}
int ans = sum;
for(int i = 0; i < n; ++i){
sum = sum - a[i] + (n - 1 - a[i]);
ans = min(ans, sum);
}
printf("%d\n", ans);
}
return 0;
}

 

HDU - 1394 Minimum Inversion Number(线段树求逆序数---点修改)的更多相关文章

  1. [HDU] 1394 Minimum Inversion Number [线段树求逆序数]

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

  2. HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对)

    HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对) 题意分析 给出n个数的序列,a1,a2,a3--an,ai∈[0,n-1],求环序列中逆序对 ...

  3. hdu - 1394 Minimum Inversion Number(线段树水题)

    http://acm.hdu.edu.cn/showproblem.php?pid=1394 很基础的线段树. 先查询在更新,如果后面的数比前面的数小肯定会查询到前面已经更新过的值,这时候返回的sum ...

  4. HDU 1394 Minimum Inversion Number 线段树

    题目: http://acm.hdu.edu.cn/showproblem.php?pid=1394 没看到多组输入,WA了一万次...... 其实很简单,有人暴力过得,我感觉归并排序.二叉排序树求逆 ...

  5. HDU 1394 Minimum Inversion Number(线段树 或 树状数组)

    题目大意:给出从 0 到 n-1 的整数序列,A0,A1,A2...An-1.可将该序列的前m( 0 <= m < n )个数移到后面去,组成其他的序列,例如当 m=2 时,得到序列 A2 ...

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

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

  7. hdu 13394 Minimum Inversion Number 线段树

    题意: 首先给你一个长度为n的序列v,你需要首先找出来逆序对(i<j && v[i]>v[j]) 然后把这个序列的最后一个元素放在第一个位置上,其他元素都向后移动一位. 一 ...

  8. hdu 1394 Minimum Inversion Number (树状数组求逆序对)

    The inversion number of a given number sequence a1, a2, ..., an is the number of pairs (ai, aj) that ...

  9. HDU 1394 Minimum Inversion Number (树状数组)

    题目链接 Problem Description The inversion number of a given number sequence a1, a2, ..., an is the numb ...

  10. HDU 1394 Minimum Inversion Number(树状数组/归并排序实现

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

随机推荐

  1. Django问题 Did you rename .....a ForeignKey

    给新加入的字段添加一个default默认值即可,让字段非空.然后在进行makemigrations,完成操作后删除相关默认值即可.

  2. 【PAT甲级】1009 Product of Polynomials (25 分)

    题意: 给出两个多项式,计算两个多项式的积,并以指数从大到小输出多项式的指数个数,指数和系数. trick: 这道题数据未知,导致测试的时候发现不了问题所在. 用set统计非零项时,通过set.siz ...

  3. c#能同时继承接口和类吗

    c#能同时继承接口和类吗?( 要你命3000条12级分类:C#/.NET语言被浏览449次2013.09.10   满意答案 mroyal450 采纳率:54%12级 2013.09.11 C# 类, ...

  4. 使用 TestFight 构建 Beta 测试版本

    ---恢复内容开始--- Beta测试属于软件开发周期中的一环,测试的重点就是让一些活生生的人去使用你的App,不断测试然后反馈.你需要让你的测试成员发现尽可能多的bug,以便你在公开发布之前将其修复 ...

  5. python 通过UDP传输文件

    使用一个简单的python脚本将一个本地文件以码流的形式,通过UDP协议发送到对端: import socket import os import stat import struct   MAX_P ...

  6. OC中四种遍历方式

    标准的C语言for循环.Objective-C 1.0出现的NSEnumerator.Objective-C 1.0出现的for in快速遍历.块遍历. 遍历的话,一般是NSArray.NSDicti ...

  7. 一、什么是Velocity及简单示例

    1.velocity简介:    velocity是一个java模板引擎技术,任何人可以使用这种简单而又强有力的模板语言去获取java对象. 在使用Velocity进行web开发时,web开发人员和j ...

  8. 伪类:after,:before的用法

    :after和:before是css3中的伪类元素.用法是像元素的前或者后插入元素.以after为例: li:after{ content: ''; color: #ff0000; } 意思是向li元 ...

  9. Day9 - H - 最少拦截系统 HDU - 1257

    某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能超过前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于 ...

  10. Git如何合并Commit

    如果你在 push 你的修改之前想要将本地多次修改后的 commit 合并一下变得更好看,可以使用下面的方法. 指定你要合并的 commit 相关的命令有两种 你可以通过指定修改过去的几个 commi ...