zoukankan      html  css  js  c++  java
  • 线段树单点更新 HDU 1394 Minimum Inversion Number

    Problem Description
    The inversion number of a given number sequence a1, a2, ..., an is the number of pairs (ai, aj) that satisfy i < j and ai > aj.

    For a given sequence of numbers a1, a2, ..., an, if we move the first m >= 0 numbers to the end of the seqence, we will obtain another sequence. There are totally n such sequences as the following:

    a1, a2, ..., an-1, an (where m = 0 - the initial seqence)
    a2, a3, ..., an, a1 (where m = 1)
    a3, a4, ..., an, a1, a2 (where m = 2)
    ...
    an, a1, a2, ..., an-1 (where m = n-1)

    You are asked to write a program to find the minimum inversion number out of the above sequences.
     
    Input
    The input consists of a number of test cases. Each case consists of two lines: the first line contains a positive integer n (n <= 5000); the next line contains a permutation of the n integers from 0 to n-1.
     
    Output
    For each case, output the minimum inversion number on a single line.
     
    Sample Input
    10 1 3 6 9 0 8 5 7 4 2
     
    Sample Output
    16
     
    题意:求最小逆序数。

    分析:线段树的一个应用,求逆序数。

    从a[0]开始扫描,找比a[0]大的个数,也就是询问区间(a[0],n-1)中点的个数,然后再插入a[0],更新父节点即可。

    思路为:tree[i]为0代表i未出现,为1则已经出现,
    然后查询时我们只要统计新加入的数到n-1这个范围内有多少个tree[i]为1,也就是当前
    数的逆序,然后累加,就是我们要求的逆序数。因为其他形式都可以由第一次求得的逆
    序数递推而来,所以只需计算一次。

    有个结论,设逆序数为sum,x[0]后面比它小的一定是x[0]个。那么移到末尾后,比x[0]大的数的后面比它小的数统统加一,也就是加(n - a[0] - 1),然后它放到末尾了,他原来的后面比它小的数变为0,也就是sum = sum + (n - a[0] - 1) - a[0];

    AC代码:

    View Code
     1 #include<stdio.h>
     2 #define maxn 5010
     3 #define lson l,m,rt << 1
     4 #define rson m+1,r,rt << 1 | 1
     5 int tree[maxn<<2],x[maxn];
     6 int min(int a,int b)
     7 {
     8     return a<b?a:b;
     9 }
    10 void PushUP(int rt)
    11 {
    12     tree[rt]=tree[rt<<1]+tree[rt<<1|1];
    13 }
    14 void build(int l,int r,int rt)
    15 {
    16     tree[rt]=0;
    17     if(l==r)
    18         return ;
    19     int m=(l+r)>>1;
    20     build(lson);
    21     build(rson);
    22 }
    23 int query(int L,int R,int l,int r,int rt)
    24 {
    25     if(L<=l&&R>=r)
    26         return tree[rt];
    27     int m=(l+r)>>1;
    28     int ret=0;
    29     if(L<=m)
    30         ret+=query(L,R,lson);
    31     if(R>m)
    32         ret+=query(L,R,rson);
    33     return ret;
    34 }
    35 void update(int p,int l,int r,int rt)
    36 {
    37     if(l==r)
    38     {
    39         tree[rt]++;
    40         return ;
    41     }
    42     int m=(l+r)>>1;
    43     if(p<=m)
    44         update(p,lson);
    45     else
    46         update(p,rson);
    47     PushUP(rt);
    48 }
    49 int main()
    50 {
    51     int i,n,sum;
    52     while(scanf("%d",&n)!=EOF)
    53     {
    54         build(0,n-1,1);
    55         sum=0;
    56         for(i=0;i<n;i++)
    57         {
    58             scanf("%d",&x[i]);
    59             sum+=query(x[i],n-1,0,n-1,1);
    60             update(x[i],0,n-1,1);
    61         }
    62         int ret=sum;
    63         for(i=0;i<n;i++)
    64         {
    65             sum+=n-x[i]-1-x[i];
    66             ret=min(ret,sum);
    67         }
    68         printf("%d\n",ret);
    69     }
    70     return 0;
    71 }
  • 相关阅读:
    mybatis中 无效的比较: invalid comparison: java.util.Date and java.lang.String
    java中日期的加减,比较,以及与String的互相转换
    Java中文件上传下载 --使用Minio
    Dubbo SPI 源码深入分析
    新建Maven项目 发布服务 注册到zookeeper
    Dubbo SPI 源码分析
    思维方法
    JDK 和 Dubbo SPI 的入门浅析Demo
    Dubbo不用注册中心实现远程调用的简单用法demo
    解决linux系统下tar解压文件报错问题
  • 原文地址:https://www.cnblogs.com/frog112111/p/2666970.html
Copyright © 2011-2022 走看看