HDU 1394 Minimum Inversion Number 线段树
Posted FriskyPuppy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 1394 Minimum Inversion Number 线段树相关的知识,希望对你有一定的参考价值。
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1394
题目大意:给出一个n排列, 进行n中变换, 求最大逆序数
解题思路: 已知一个数列的逆序数, 那么他的变换可以O(1)求出来, 所以现在的主要问题就是求一组排列的逆序数, n 小于等于5000, 完全可以暴力, 但是现在用线段树做。由于是一组n排列, 而且我们只关心一个数前面的比他大的数, 那当我们插入a[i]时, 只需要查询0 ~ i-1 中 a[i] ~ n-1 内的数的个数就可以了, 我们可以先造一颗0的空树, 这样我们查询的时候就就直接查全部序列就可以。(吃饭去了)
代码:
#include <iostream> #include <cstdio> #include <string> #include <vector> #include <map> #include <cstring> #include <iterator> #include <cmath> #include <algorithm> #include <stack> #include <deque> #include <map> #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 const int maxn = 5000+7; using namespace std; int sum[4*maxn]; int arr[maxn]; void Pushplus( int rt ) { sum[rt] = sum[rt<<1] + sum[rt<<1|1]; return; } void build( int l, int r, int rt ) { sum[rt] = 0; if( l == r ) return; int m = (l + r) >> 1; build( lson ); build( rson ); return; } int Query( int L, int R, int l, int r, int rt ) { if( L <= l && r <= R ) { return sum[rt]; } int m = (l + r) >> 1; int ret = 0; if( L <= m ) ret += Query( L, R, lson ); if( R > m ) ret += Query( L, R, rson ); return ret; } void update(int p, int l, int r, int rt) { if( l == r ) { sum[rt]++; return; } int m = (l+r) >> 1; if( p <= m ) update(p, lson); else update(p, rson); Pushplus(rt); } int main() { int n; while( scanf( "%d", &n ) == 1 ) { build( 0, n-1, 1 ); int sum = 0; for( int i = 0; i < n; i++ ) { scanf( "%d", arr + i ); sum += Query( arr[i], n-1, 0, n-1, 1 ); update(arr[i], 0, n-1, 1); } int ret = sum; for( int i = 0; i < n; i++ ) { sum += n - arr[i] - arr[i] - 1; ret = min( ret, sum ); } printf( "%d\n", ret ); } }
思考:
以上是关于HDU 1394 Minimum Inversion Number 线段树的主要内容,如果未能解决你的问题,请参考以下文章
hdu1394 [Minimum Inversion Number]
HDU 1394 Minimum Inversion Number
HDU1394 Minimum Inversion Number
[HDU1394]Minimum Inversion Number