当前位置: 首页 > news >正文

《P1637 三元上升子序列》

题目描述

Erwin 最近对一种叫 thair 的东西巨感兴趣。。。

在含有 n 个整数的序列 a1​,a2​,…,an​ 中,三个数被称作thair当且仅当 i<j<k 且 ai​<aj​<ak​。

求一个序列中 thair 的个数。

输入格式

开始一行一个正整数 n,

以后一行 n 个整数 a1​,a2​,…,an​。

输出格式

一行一个整数表示 thair 的个数。

输入输出样例

输入 #1复制

4
2 1 3 4

输出 #1复制

2

输入 #2复制

5
1 2 2 3 4

输出 #2复制

7

说明/提示

样例2 解释

7 个 thair 分别是:

  • 1 2 3
  • 1 2 4
  • 1 2 3
  • 1 2 4
  • 1 3 4
  • 2 3 4
  • 2 3 4
数据规模与约定
  • 对于 30% 的数据 保证 n≤100;
  • 对于 60% 的数据 保证 n≤2000;
  • 对于 100% 的数据 保证 1≤n≤3×104,1≤ai​≤105。

代码实现:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

// 树状数组类
class FenwickTree {
private:
    vector<int> tree;
    int size;

public:
    FenwickTree(int n) : size(n), tree(n + 1, 0) {}

    void update(int idx) {
        while (idx <= size) {
            tree[idx]++;
            idx += idx & -idx;
        }
    }

    int query(int idx) {
        int sum = 0;
        while (idx > 0) {
            sum += tree[idx];
            idx -= idx & -idx;
        }
        return sum;
    }
};

int main() {
    int n;
    cin >> n;
    
    vector<int> a(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    
    // 离散化处理
    vector<int> b = a;
    sort(b.begin(), b.end());
    b.erase(unique(b.begin(), b.end()), b.end());
    
    // 计算left[j]:j之前小于a[j]的元素个数
    vector<int> left(n, 0);
    FenwickTree ft1(b.size());
    for (int j = 0; j < n; j++) {
        int idx = lower_bound(b.begin(), b.end(), a[j]) - b.begin() + 1;
        left[j] = ft1.query(idx - 1);
        ft1.update(idx);
    }
    
    // 计算right[j]:j之后大于a[j]的元素个数
    vector<int> right(n, 0);
    FenwickTree ft2(b.size());
    for (int j = n - 1; j >= 0; j--) {
        int idx = lower_bound(b.begin(), b.end(), a[j]) - b.begin() + 1;
        // j之后的元素总数是n-1-j个
        // ft2.query(idx)表示到当前为止(从右到左)小于等于a[j]的元素个数
        // 所以right[j] = (j之后的元素总数) - (小于等于a[j]的元素个数)
        right[j] = (n - 1 - j) - ft2.query(idx);
        ft2.update(idx);
    }
    
    // 计算所有thair的数量
    long long count = 0;
    for (int j = 0; j < n; j++) {
        count += (long long)left[j] * right[j];
    }
    
    cout << count << endl;
    
    return 0;
}

相关文章:

  • #华为昇腾#华为计算#昇腾开发者计划2025#
  • Redis学习笔记——黑马点评 附近商铺到UV统计 完结
  • 中州养老:学会设计数据库表
  • 银行账户管理系统01
  • 图解Git中Rebase与Merge的区别
  • Linux中《动/静态库原理》
  • WireShark网络取证分析第一集到第五集和dvwa靶场环境分析漏洞
  • C++并发编程-5.C++ 线程安全的单例模式演变
  • 暑假复习篇之五子棋①
  • MongoDB06 - MongoDB 地理空间
  • Cursor 教程:用 Cursor 创建第一个 Java 项目
  • Blood-Cat 公網網路攝像機泄露收集器:查看指定國家地區攝像
  • 左神算法之螺旋打印
  • Docker 镜像构建 - Aliyun
  • 深入探索 GORM:Go 语言中的强大 ORM 工具
  • 熟悉 PyCharm
  • 常识科普:去杠杆通常分为四个步骤
  • Spring Cloud:分布式事务管理与数据一致性解决方案
  • KPL战队近五年热度指数
  • springboot小区物业管理系统