• HDU 1394 & ZOJ 1484 Minimum Inversion Number


    (更新点查询区间)

    这题重在想到,写代码很容易了。。这题是利用线段树求逆序数,不按给定的顺序建树,而是有序地插入。比如每插入一个数,就统计之前插入的那些数里比他大的有多少个,这个数就是此时的逆序数,然后累加每个的逆序数,就是整个原始序列的逆序数,怎么统计呢?前面说了,是有序的插入,查询比它大的数岂不是查它右边就好了?即查询a[i]~n-1中插入了多少数,凡插入了的即是比他大的。这样,总的逆序数就出来了。现在求一个最小值。这里有个结论,因为每次都把第一个移到最后即可,考虑第一个元素,x[0]是此时的逆序数,把x[0]放到最后,这时要增加原来比a[0]大的个数(即n-a[0]-1个)个逆序数,同时要减少a[0]个逆序数,因为放到后面去了,前面的那些比它小的数(a[0]个)不再构成逆序数。这是即 sum = sum + n - a[i] - 1 - a[i] ,跑一边循环求最小值。。感觉自己也没说清楚,还是不懂的自己体会一下吧。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <utility>
    #include <cstdlib>
    using namespace std;
    #define N 5010
    
    int tree[4*N];
    int a[N];
    
    void build(int l,int r,int rt)
    {
        tree[rt] = 0;
        if(l == r)
        {
            return;
        }
        int mid = (l+r)/2;
        build(l,mid,2*rt);
        build(mid+1,r,2*rt+1);
    }
    
    void update(int l,int r,int pos,int rt)
    {
        if(l == r)
        {
            tree[rt]++;
            return;
        }
        int mid = (l+r)/2;
        if(pos<=mid)
            update(l,mid,pos,2*rt);
        else
            update(mid+1,r,pos,2*rt+1);
        tree[rt] = tree[2*rt]+tree[2*rt+1];
    }
    
    int query(int l,int r,int aa,int bb,int rt)
    {
        if(aa>r||bb<l)
            return 0;
        if(aa<=l&&bb>=r)
            return tree[rt];
        int mid = (l+r)/2;
        int res = 0;
        if(aa<=mid)
            res += query(l,mid,aa,bb,2*rt);
        if(bb>mid)
            res += query(mid+1,r,aa,bb,2*rt+1);
        return res;
    }
    
    int main()
    {
        int n,i;
        int sum;
        while(scanf("%d",&n)!=EOF)
        {
            build(0,n-1,1);
            sum = 0;
            for(i=0;i<n;i++)
            {
                scanf("%d",&a[i]);
                sum += query(0,n-1,a[i],n-1,1);
                update(0,n-1,a[i],1);
            }
            int ans = 100000000;
            for(i=0;i<n;i++)
            {
                sum = sum+n-a[i]-1-a[i];
                ans = min(ans,sum);
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code

    作者:whatbeg
    出处1:http://whatbeg.com/
    出处2:http://www.cnblogs.com/whatbeg/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
    更多精彩文章抢先看?详见我的独立博客: whatbeg.com

  • 相关阅读:
    使用DBUtils获取Blob类型数据
    关于 JupyterLab 与 Pandas 资源整理
    关于 Conda 在 MacOS Catalina 环境变量问题
    推荐一个符合 OIDC 规范的 JAVA 客户端
    关于 Chrome 的 Kiosk 模式
    Kubernetes 中的服务发现与负载均衡
    Prometheus 监控领域最锋利的“瑞士军刀”
    CD 基金会、Jenkins、Jenkins X、Spinnaker 和 Tekton 的常问问题
    Installing on Kubernetes with NATS Operator
    升级 ASP.NET Core 3.0 设置 JSON 返回 PascalCase 格式与 SignalR 问题
  • 原文地址:https://www.cnblogs.com/whatbeg/p/3490070.html
Copyright © 2020-2023  润新知