题意:给定一个序列,求分别将前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. Set和Map集合的比较

     HashSet:数据进行hashCode比较,然后进行equals方法比较,根据比较结果进行排序.如果要对对象进行排序,对象类要重写hashCode和equals方法.TreeSet:如果要对对象进 ...

  2. js 判断时间大小

    //判断结束时间一定要大于开始时间 function comparativeTime(){ var isok=true; //早餐配送时间 var breakfastScanTimeMin = $(& ...

  3. Cortex-M3学习小结

  4. Linux三剑客之awk精讲(基础与进阶)

    第1章 awk基础入门 要弄懂awk程序,必须熟悉了解这个工具的规则.本实战笔记的目的是通过实际案例或面试题带同学们熟练掌握awk在企业中的用法,而不是awk程序的帮助手册. 1.1 awk简介 一种 ...

  5. [aac @ ...] Specified sample format s16 is invalid or not supported

    在使用FFmpeg打开编码器的时候出现以下错误: [aac @ 000001da19fd7200] Specified sample format s16 is invalid or not supp ...

  6. leetcode刷题-- 3.二分查找

    二分查找 正常实现 题解 public int binarySearch(int[] nums, int key) { int l = 0, h = nums.length - 1; while (l ...

  7. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 按钮:按钮被点击

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  8. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 辅助类:"text-warning" 类的文本样式

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  9. 每天一点点之vue框架 watch监听变量(深度监听)

    <div> <p>FullName: {{fullName}}</p> <p>FirstName: <input type="text& ...

  10. eclipse搜索类快捷键

    习惯的编辑器可以提高编程效率,熟悉的快捷键可以提高工作效率,本文更新eclipse中常用的搜索快捷键 打开资源快捷键:Ctrl+Shift+R 通过在搜索框中输入名字可以很方便的在项目或工作空间中找某 ...