T1009 Triple Inversions

T1009 Triple Inversions

题目大意

如果在一个序列A中存在i<j<k, 且A_i>A_j>A_k,则(A_i, A_j, A_k)是一个三元逆序对。现要求统计给定数组中的三元逆序对的数量。

题目限制条件

  • 时间限制:300ms
  • 内存限制:64MB

本题考察知识点

  • 树状数组

解题思路

用树状数组求二元逆序对是一道很经典的题。我们回顾一下求二元逆序对的过程:从后向前扫描,用树状数组维护每个数字出现的次数,本质上维护的是以每个数字为开头的一元逆序对的个数。当然,一元逆序对也就是数字本身出现的次数。

现在要求三元逆序对,自然想到用两个树状数组分别维护以每个数字为开头的一元逆序对二元逆序对出现的次数。

注意整数类型要用long long,用int的话会有两个case溢出。

AC代码

/*
    Data Structure and Algorithm.
    Created by CLion
    Author: Depressant
    Date: 2022.4.26
    Time: 下午 10:03
*/
#include "bits/stdc++.h"

#define maxn 100005
typedef long long ll;
int N;
ll cnt = 0;
int arr[maxn];

struct FenwickTree {
    int len{};
    std::vector<ll> _v;


    void setLen(int l) {
        len = l;
        _v.resize(l + 1);
    }

    static int lowbit(int x) { return x & (-x); }

    void update(int pos, ll val) {
        while (pos <= len) {
            _v[pos] += val;
            pos += lowbit(pos);
        }
    }

    ll query(int pos) {
        ll ret = 0;
        while (pos > 0) {
            ret += _v[pos];
            pos -= lowbit(pos);
        }
        return ret;
    }
};

FenwickTree ft1, ft2;

void init() {

}

void read() {
    std::cin >> N;
    for (int i = 0; i < N; ++i) {
        scanf("%d", &arr[i]);
    }
    ft1.setLen(N);
    ft2.setLen(N);
}

void solve() {
    for (int i = N - 1; i >= 0; --i) {
        ll tmp = ft1.query(arr[i] - 1);
        ft1.update(arr[i], 1);
        cnt += ft2.query(arr[i] - 1);
        ft2.update(arr[i], tmp);
    }
    std::cout << cnt;
}

int main() {
//    freopen("Depressant.txt", "r", stdin);
    init();
    read();
    solve();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值