• 逆序对(树状数组)


    链接:https://www.nowcoder.com/acm/contest/77/A
    来源:牛客网

    逆序数
    时间限制:C/C++ 2秒,其他语言4秒
    空间限制:C/C++ 131072K,其他语言262144K
    64bit IO Format: %lld

    题目描述

    在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。比如一个序列为4 5 1 3 2, 那么这个序列的逆序数为7,逆序对分别为(4, 1), (4, 3), (4, 2), (5, 1), (5, 3), (5, 2),(3, 2)。

    输入描述:

    第一行有一个整数n(1 <= n <= 100000),  然后第二行跟着n个整数,对于第i个数a[i],(0 <= a[i] <= 100000)。

    输出描述:

    输出这个序列中的逆序数
    示例1

    输入

    5
    4 5 1 3 2

    输出

    7
    先离散化,得到数组b[i],
    a:88 11 62 5 23
    b:5  2  4  1 3
    i为1,那么在5的位置+1,
    即 1 2 3 4 5
    sum[i] 0 0 0 0 1

    在计算5及5之前有几个数,为1个数,再用总数-1=4,代表和5组成逆序对的有4个数。
     1 #include <iostream>
     2 #include <cstring>
     3 #include <string>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 int T, n;
     8 int sum[100005];
     9 
    10 struct node
    11 {
    12     int pos, x;
    13 }a[100005];
    14 int b[100005];
    15 
    16 bool cmp(node x, node y)
    17 {
    18     return x.x < y.x;
    19 }
    20 
    21 void update(int pos, int val)
    22 {
    23     while (pos <= n)
    24     {
    25         sum[pos] += val;
    26         pos += (pos&(-pos));//加上最末尾的1所代表的个数,12,1100,+4+8
    27     }
    28 }
    29 
    30 int query(int pos)
    31 {
    32     int rec = 0;//13为1101,减去末尾的1(1),1100,再减去末尾的1(4),1000,再减(8),000
    33     while (pos > 0)
    34     {
    35         rec+=sum[pos];
    36         pos -= (pos&(-pos));
    37     }
    38     return rec;
    39 }
    40 
    41 int main()
    42 {
    43     long long nxs = 0;
    44     cin >> n;
    45     memset(sum, 0, sizeof(sum));
    46     for (int i = 1,x; i <= n; i++)
    47     {
    48         cin >> a[i].x;
    49         a[i].pos = i;//记录原先的位置,88 11 62 5 23
    50     }
    51     sort(a + 1, a + n + 1, cmp);
    52     for (int i = 1; i <= n; i++)
    53     {
    54         b[a[i].pos] = i;//5原来在4的位置b【4】=1
    55         //a:88 11 62 5 23
    56         //b:5  2  4  1 3
    57     }
    58     /*for (int i = 1; i <= n; i++)
    59     {
    60         cout << b[i] << " ";
    61     }
    62     cout << endl;*/
    63     for (int i = 1; i <= n; i++)
    64     {
    65         update(b[i], 1);
    66         int temp = query(b[i]);
    67         nxs += b[i] - temp;
    68     }
    69     cout << nxs << endl;
    70 }
  • 相关阅读:
    数据库外连接和内连接详解
    关于省市联动问题的分析
    邮箱验证修改密码,通过邮箱找回密码
    格式化Json传递的日期
    项目中验证码的使用
    水仙花数
    回文数
    冒泡排序
    《终结者·洛谷小说》总集
    题解 CF151A 【Soft Drinking】
  • 原文地址:https://www.cnblogs.com/caiyishuai/p/8474716.html
Copyright © 2020-2023  润新知