• Haircut(剪发)


    Haircut(剪发)

    题目描述

    Farmer John 由于对整理他难以整平的头发感到疲惫,于是决定去理发。他有一排 N 缕头发,第 i缕头发初始时长度为 A_i 微米理想情况下,他想要他的头发在长度上单调递增,所以他定义他的头发的“不良度”为逆序对的数量:满足 i < 及 A_i > A_j的二元对 (i,j)(i,j)。
    对于每一个 j=0,1,…,N−1,Farmer John 想要知道他所有长度大于 j的头发的长度均减少到 j时他的头发的不良度。

    题目分析

    题目可以理解为头发长度最长为 j 时3的逆序对数量。对于头发长度为n时的逆序对数,同样是对其后面大于n的情况下的贡献度。从小到达枚举j,每次累计贡献度。

    例如,当 j 为 3时,我们求得每个3前大于3(即为4与4+)的数字个数之和,也就是 j 等于4时增加的逆序对数。以此类推。

    对于求逆序对。我们可以使用树状数组。设原序列为a[N],将序列 a 从小到大排列。1~n个位置对应的树状数组上的数初始化为 1

    遍历到一个 a[i],将其在原序列中的位置 u 对应的树状数组的值改为 0,此时其贡献度为 u 之前1的个数sum(u-1),因比a[i]小的数会先遍历到,相应的树状数组的位置的值位置会置0,所以u前还在的 1 均为比a[i]大的数。

    code

    #include
    
    using namespace std;
    
    const int N = 1e6 + 10;
    typedef long long ll;
    
    int n, m, k, t;
    int tr[N];
    
    struct node
    {
        int val, num;
    }q[N];
    
    bool cmp(node a, node b)
    {
        if(a.val == b.val) return a.num < b.num;
        return a.val < b.val;
    }
    
    int lowbit(int x)
    {
        return x & -x;
    }
    
    void add(int x, int c)
    {
        for(int i = x; i <= n; i += lowbit(i)) tr[i] += c;
    }
    
    int sum(int x)
    {
        int res = 0;
        for(int i = x; i; i -= lowbit(i)) res += tr[i];
        return res;
    }
    
    int main()
    {
        cin >> n;
    
        for(int i = 1; i <= n; i ++)
        {
            int u;
            cin >> u;
            q[i].val = u;
            q[i].num = i;
            add(q[i].num, 1);
        }
    
        sort(q + 1, q + n + 1, cmp);
    
        ll ans = 0, res = 1;
        for(int i = 0; i < n; i ++)
        {
            cout << ans << "\n";
            int tem = res;
            while(i == q[tem].val)
            {
                ans += sum(q[tem].num - 1);
                add(q[tem].num, - 1);
                tem ++;
            }
    
            res = tem;
        }
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
  • 相关阅读:
    2022谷粒商城学习笔记(十三)ElasticSearch安装和商品上架功能
    实习记录(一):MySQL时间偏差问题的发现与解决
    QGIS:使用QGIS进行矢量和栅格数据的裁剪
    Qt·事件处理机制
    Redis RDB持久化与AOF 持久化详解
    在uniapp中,如何去掉一些不想要的权限,
    Leetcode—2520.统计能整除数字的位数【简单】
    代码随想录12——栈与队列:150.逆波兰表达式、239滑动窗口最大值、347前K个高频元素
    线程三连鞭之“线程基础”
    数据结构-二叉树-堆
  • 原文地址:https://blog.csdn.net/m0_60610120/article/details/126366325