HDU 1394 Minimum Inversion Number(线段树求最小逆序数对)

ACM

题目地址:HDU 1394 Minimum Inversion Number

题意: 

给一个序列由[1,N]构成。能够通过旋转把第一个移动到最后一个。 

问旋转后最小的逆序数对。

分析: 

注意,序列是由[1,N]构成的,我们模拟下旋转,总的逆序数对会有规律的变化。 

求出初始的逆序数对再循环一遍即可了。

至于求逆序数对,我曾经用归并排序解过这道题:点这里。 

只是因为数据范围是5000。所以全然能够用线段树或树状数组来做:求某个数的作为逆序数对的后面部分的对数,能够在前面的数中查询小于这个数的数的个数。 

直接在线一边加一边查即可了,复杂度为O(nlogn)。

只是老实说,这题的单个数没有太大,不然线段树和树状数组都开不下的。所以求逆序数对的最佳算法应该是归并排序解。

代码:

/*
* Author: illuz <iilluzen[at]gmail.com>
* Blog: http://blog.csdn.net/hcbbt
* File: 1394_segment_tree.cpp
* Create Date: 2014-08-05 10:08:42
* Descripton: segment tree
*/ #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define repf(i,a,b) for(int i=(a);i<=(b);i++) #define lson(x) ((x) << 1)
#define rson(x) ((x) << 1 | 1) typedef long long ll; const int N = 5010;
const int ROOT = 1; // below is sement point updated
struct seg {
ll w;
}; struct segment_tree {
seg node[N << 2]; void update(int pos) {
node[pos].w = node[lson(pos)].w + node[rson(pos)].w;
} void build(int l, int r, int pos) {
if (l == r) {
node[pos].w = 0;
return;
}
int m = (l + r) >> 1;
build(l, m, lson(pos));
build(m + 1, r, rson(pos));
update(pos);
} // add the point x with y
void modify(int l, int r, int pos, int x, ll y) {
if (l == r) {
node[pos].w += y;
return;
}
int m = (l + r) >> 1;
if (x <= m)
modify(l, m, lson(pos), x, y);
else
modify(m + 1, r, rson(pos), x, y);
update(pos);
} // query the segment [x, y]
ll query(int l, int r, int pos, int x, int y) {
if (x <= l && r <= y)
return node[pos].w;
int m = (l + r) >> 1;
ll res = 0;
if (x <= m)
res += query(l, m, lson(pos), x, y);
if (y > m)
res += query(m + 1, r, rson(pos), x, y);
return res;
} // remove the point that the sum of [0, it] is x, return its id
int remove(int l, int r, int pos, ll x) {
if (l == r) {
node[pos].w = 0;
return l;
}
int m = (l + r) >> 1;
int res;
if (x < node[lson(pos)].w)
res = remove(l, m, lson(pos), x);
else
res = remove(m + 1, r, rson(pos), x - node[lson(pos)].w);
update(pos);
return res;
}
} sgm; int n, a[N], b[N], t, sum, mmin; int main() {
while (~scanf("%d", &n)) {
sgm.build(1, n, ROOT);
sum = 0;
repf (i, 1, n)
scanf("%d", &a[i]);
for (int i = n; i >= 1; i--) {
b[i] = sgm.query(1, n, ROOT, 1, a[i] + 1);
sum += b[i];
sgm.modify(1, n, ROOT, a[i] + 1, 1);
}
mmin = sum;
repf (i, 1, n) {
sum = sum - a[i] + (n - 1 - a[i]);
mmin = min(mmin, sum);
}
cout << mmin << endl;
}
return 0;
}

最新文章

  1. redis cluster php 客户端 predis
  2. js中字符串和数组相互转化的方法
  3. hdu 4751 2013南京赛区网络赛 二分图判断 **
  4. 自己动手写RTP服务器——关于RTP协议
  5. Java向上转型与向下转型
  6. SQLserver 表字段修改语句
  7. ORACLE数据库用户账号处于expired状态如何处理
  8. Machine Learning for hackers读书笔记(三)分类:垃圾邮件过滤
  9. JAVA多线程学习--哲学家就餐问题
  10. 对jQuery.isArray方法的分析
  11. jni 入门 android的C编程之旅 ---&gt;环境搭建&amp;&amp;helloworld
  12. Tensorflow开发环境配置及其基本概念
  13. Mybash的实现
  14. 【刷水】之USACO2008资格赛(Bzoj1599-1603)
  15. Python 正则表达式相关问题
  16. How to create an rpm package
  17. 自学java第六周的总结
  18. 2-Qt关闭子窗口时执行特定代码
  19. Atom编辑器汉化
  20. 命令之 ulimit

热门文章

  1. 75.《nodejs开发指南》express4.x版-微博案例完整实现
  2. 关于ajax访问express服务器的跨域问题
  3. 什么是CSS重置,有些什么作用?
  4. 小项目: low版本的 员工信息程序:
  5. the night the room
  6. PCA and Whitening on natural images
  7. 一台服务器安装运行多个Tomcat及注册服务
  8. Java: 数据类型
  9. groupdel---删除指定的工作组
  10. django shell 操作