[HDOJ1394]Minimum Inversion Number(线段树,逆序数)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[HDOJ1394]Minimum Inversion Number(线段树,逆序数)相关的知识,希望对你有一定的参考价值。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394
题意:一个数的逆序数为inv,然后求这个数列的第一个数后变为最后一个数,过程中逆序数最小的时候的逆序数。
用线段树,先建立一棵空树,之后向树内插点。在插入之前进行一次统计,求出比这个数大的个数,累计相加。得出当前逆序数。也可用归并排序、树状数组之类的方法。
之后移动每次的第一个数,可以用二分搜两遍,求出多少个数比它大,多少个数比它小。用当前逆序数加上比它大的数的个数,减去比它小的个数即可求得当前逆序数。
也可以得到规律:第i个数变成第n-1数的时候,要减去后面比它小的数(tmp[i]个),要加上后面比它大的数(n-tmp[i]+1个)。
1 #include <algorithm> 2 #include <iostream> 3 #include <iomanip> 4 #include <cstring> 5 #include <climits> 6 #include <complex> 7 #include <fstream> 8 #include <cassert> 9 #include <cstdio> 10 #include <cstdlib> 11 #include <bitset> 12 #include <vector> 13 #include <deque> 14 #include <queue> 15 #include <stack> 16 #include <ctime> 17 #include <set> 18 #include <map> 19 #include <cmath> 20 21 using namespace std; 22 23 #define lson l, m, rt << 1 24 #define rson m + 1, r, rt << 1 | 1 25 const int maxn = 6666; 26 int num[maxn<<2]; 27 int tmp[maxn]; 28 29 void pushUP(int rt) { 30 num[rt] = num[rt<<1] + num[rt<<1|1]; 31 } 32 33 void build(int l, int r, int rt) { 34 num[rt] = 0; 35 if(l == r) { 36 return; 37 } 38 int m = (l + r) >> 1; 39 build(lson); 40 build(rson); 41 } 42 43 void update(int p, int l, int r, int rt) { 44 if(l == r) { 45 num[rt]++; 46 return; 47 } 48 int m = (l + r) >> 1; 49 if(p <= m) { 50 update(p, lson); 51 } 52 else { 53 update(p, rson); 54 } 55 pushUP(rt); 56 } 57 58 int query(int L, int R, int l, int r, int rt) { 59 if(L <= l && r <= R) { 60 return num[rt]; 61 } 62 int m = (l + r) >> 1; 63 int cur = 0; 64 if(L <= m) { 65 cur += query(L, R, lson); 66 } 67 if(R > m) { 68 cur += query(L, R, rson); 69 } 70 return cur; 71 } 72 73 int main() { 74 // freopen("in", "r", stdin); 75 int n; 76 while(~scanf("%d", &n)) { 77 build(0, n-1, 1); 78 int inv = 0; 79 for(int i = 0; i < n; i++) { 80 scanf("%d", &tmp[i]); 81 inv += query(tmp[i], n-1, 0, n-1, 1); 82 update(tmp[i], 0, n-1, 1); 83 } 84 int ans = 0; 85 for(int i = 0; i < n; i++) { 86 inv = inv - tmp[i] + n - tmp[i] - 1; 87 ans = min(ans, inv); 88 } 89 printf("%d\n", ans); 90 } 91 return 0; 92 }
以上是关于[HDOJ1394]Minimum Inversion Number(线段树,逆序数)的主要内容,如果未能解决你的问题,请参考以下文章
HDU 1394 - Minimum Inversion Number
hdu 1394 Minimum Inversion Number
hdu1394 [Minimum Inversion Number]