• 逆序对(树状数组)


    链接: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 }
  • 相关阅读:
    java+opencv实现图像灰度化
    java实现高斯平滑
    hdu 3415 单调队列
    POJ 3368 Frequent values 线段树区间合并
    UVA 11795 Mega Man's Mission 状态DP
    UVA 11552 Fewest Flops DP
    UVA 10534 Wavio Sequence DP LIS
    UVA 1424 uvalive 4256 Salesmen 简单DP
    UVA 1099 uvalive 4794 Sharing Chocolate 状态DP
    UVA 1169uvalive 3983 Robotruck 单调队列优化DP
  • 原文地址:https://www.cnblogs.com/caiyishuai/p/13271167.html
Copyright © 2020-2023  润新知