• HDU1394 Minimum Inversion Number 线段树


      题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1394

      题目大意:定义逆序数, 一个数列前面的数比后面的数大的数对的个数, 给出数列, 求逆序数。

      解题思路:我现在学习的是线段树, 所以我用线段树的思想去解决问题。暴力是n^2的复杂度, 但是只要知道了第一个数列的逆序数, 其他的都可以通过用O(1) 的方式得到, 所以关键是求初始序列的逆序数, 暴力方法是n^2, 由于最大不超过n所以问题就转化为了插入一个a[i], 求前i-1个数中a[i]~n的数的个数。这就是线段树的一个查询功能。 问题就转化为O(nlogn)了。

      代码:

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    #define lson l, m, rt << 1
    #define rson m+1, r, rt << 1 | 1
    const int maxn = 5555;
    int sum[maxn<<2];
    
    void PushUP(int rt) {
        sum[rt] = sum[rt<<1] + sum[rt<<1|1];
    }
    
    void build(int l, int r, int rt) {
        sum[rt] = 0;
        if( l == r ) return;
        int m = (l+r) >> 1;
        build(lson);
        build(rson);
    }
    
    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);
        PushUP(rt);
    }
    
    int query( int L, int R, int l, int r, int rt) {
        if( L <= l && r <= R ) {
            return sum[rt];
        }
        int m = (r+l) >> 1;
        int ret = 0;
        if( L <= m ) ret += query(L, R, lson);
        if( R > m ) ret += query(L, R, rson);
        return ret;
    }
    int x[maxn];
    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", &x[i]);
                sum += query(x[i], n-1, 0, n-1, 1);
                update(x[i], 0, n-1, 1);
            }
            int ret = sum;
            for( int i = 0; i < n; i++ ) {
                sum += n - x[i] - x[i] - 1;
                ret = min( ret, sum );
            }
            printf( "%d\n", ret );
        }
        return 0;
    }
    View Code

      思考:  我接触线段树的时间实在是很短, 所以很多问题联系不起来。线段树为什么要叫线段树呢, 因为他处理的就是区间问题, 所以如果将问题转化为区间查询问题, 就可以用线段树解决问题,当然还有更新节点等一些很麻烦的事情, 所以说还得慢慢做题积累, 一个月后我感觉线段树差不多会入门了。

  • 相关阅读:
    全方位深度剖析--性能测试之LoardRunner 介绍
    国外性能测试博客
    由我主讲的软件测试系列视频之性能测试系列视频讲座目录出炉了
    性能测试之系统监控工具nmon
    性能测试学习内容指南
    性能测试之操作系统计数器分析方法
    JAVA正则表达式:Pattern类与Matcher类详解
    (总结)密码破解之王:Ophcrack彩虹表(Rainbow Tables)原理详解(附:120G彩虹表下载)
    border-collapse实现表格细线边框
    安卓造成内存泄露的几个原因
  • 原文地址:https://www.cnblogs.com/FriskyPuppy/p/6949991.html
Copyright © 2020-2023  润新知