HDU 1394 Minimum Inversion Number
2016-05-31 21:46
381 查看
题目大意
给你一个序列,序列长度为n,序列中只包括0…..n-1这n个数,我们可以将这个序列的第一个数可以放到最后一个数,得到新序列,求这些序列中逆序对最小为多少。题目分析
逆序数计算方法是:在逐个元素读取原始数列时,每次读取都要查询当前已读取元素中大于当前元素的个数,加到sum里,最后得到的sum即为原始数列的逆序数。接下来找数列平移后得到的最小逆序数,假设当前序列逆序数是sum,那么将a[0]移到尾部后逆序数的改变是之前比a[0]大的数全部与尾部a[0]组合成逆序数,假设数量为x,则x=n-1-a[0],而之前比a[0]小的数(也就是之前能和a[0]组合为逆序数的元素)不再与a[0]组合成逆序数,假设数量为y,则y=n-x-1,这样,新序列的逆序数就是sum+x-y=sum-2*a[0]+n-1;#include <cstdio> #include <algorithm> using namespace std; #define mid (L+R)/2 #define lson o<<1, L, mid #define rson o<<1|1, mid+1, R const int maxn = 5005; int sum[maxn<<2]; void pushup(int o){ sum[o] = sum[o<<1] + sum[o<<1|1]; } void build(int o,int L,int R){ sum[o] = 0; if(L == R) return ; build(lson); build(rson); } void update(int o,int L,int R,int p) { if(L == R){ sum[o]++; return ; } if(p <= mid) update(lson, p); else update(rson, p); pushup(o); } int query(int o,int L,int R,int l,int r) { if(l <= L && R <= r) return sum[o]; int ret = 0; if(l <= mid) ret += query(lson, l, r); if(r > mid) ret += query(rson, l, r); return ret; } int a[maxn]; int main() { int n; while(scanf("%d", &n) != EOF) { build(1, 0, n-1); int sum = 0; for(int i = 0; i < n; i++) { scanf("%d", &a[i]); sum += query(1, 0, n-1, a[i], n-1); update(1, 0, n-1, a[i]); } int ret = sum; for(int i = 0; i < n; i++) { sum += n - 2*a[i] - 1; ret = min(ret, sum); } printf("%d\n", ret); } return 0; }
相关文章推荐
- 指向学生类的指针
- Android__数据存储
- 《人月神话》阅读笔记01
- Codeforces 639B——Bear and Forgotten Tree 3——————【构造、树】
- pixhawk(ArduCopter V3.3)源码分析—导航制导部分
- Oracle 11G 维护配置命令
- TQ335X开发板内核3.17.2移植和busybox移植
- HDU 3308 LCIS 线段树维护区间lcs
- Spring事务的隔离级别
- count(*),count(1)和count(主键)的区别
- Caffe Ubuntu 下的调试
- vi编辑器
- java数据结构之循环双链表
- 数组元素过半问题
- android.os.Build代码翻译
- 2016年5月英语总结
- shell中$(( ))与$( )还有${ }的区别
- LeetCode 326. Power of Three
- java之用户登录界面
- bootStrap实习原理