最大上升三元组数量
467 字
2 分钟
最大上升三元组数量
数组离散化 树状数组 前缀和
思路
要求统计满足 且 的上升三元组数量。把每个位置 当作三元组的中间元素,问题拆成两步:
- 第一层(树状数组 f1):从左往右扫描,
f1.add(idx, 1)记录值idx出现次数。对当前值idx,f1.query(idx - 1)就是它左边比它小的数的个数,记作 。 - 第二层(树状数组 f2):
f2.add(idx, small_j),即在位置idx上累加「以某个值结尾、且比它小的左边元素数」。这样f2.query(idx - 1)累计的就是所有「两两上升对」中,右端值比idx小的对数。
扫到 i 时执行 ans += f2.query(idx - 1),即以 作为第三个元素,能接上的上升对数量。三层递推:单个数 → 上升对 → 上升三元组。
值域可能很大(long long),所以先对数组离散化(排序副本 + lower_bound 映射),再把离散化后的排名当作树状数组下标。
复杂度 ,空间 。
#include <bits/stdc++.h>using namespace std;
const int MAXN = 3e4+10;typedef long long ll;
class MyTree {public: vector<int> v; int sz; MyTree(int sz) { this->sz = sz; v.resize(sz + 1); }
int lowbit(int x) { return x & (-x); }
void add(int x, int value) { while (x <= sz) { v[x] += value; x += lowbit(x); } }
int query(int x) { int sum = 0; while (x > 0) { sum += v[x]; x -= lowbit(x); } return sum; }};
MyTree f1(MAXN), f2(MAXN);
void solve() { int n; cin >> n;
vector<ll> arr(n + 1); vector<ll> sorted_arr(n + 1);
for (int i = 1; i <= n; i++) { cin >> arr[i]; sorted_arr[i] = arr[i]; // 复制数组用于排序 }
sort(next(begin(sorted_arr)), end(sorted_arr)); // 仅排序副本 auto f = [&](ll x) { return lower_bound(next(begin(sorted_arr)), end(sorted_arr), x) - sorted_arr.begin(); };
ll ans = 0; for (int i = 1; i <= n; i++) { int idx = f(arr[i]); f1.add(idx, 1); f2.add(idx, f1.query(idx - 1)); // 确保索引合法 ans += f2.query(idx - 1); } cout << ans << endl;}
int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
solve(); return 0;}文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!
相关文章智能推荐
1
数组离散化
数据结构与算法数组离散化的三种 C++ 写法:sort+unique、lower_bound 映射与宏封装。
2
Wooden Toy Festival 题解:二分答案与贪心验证
数据结构与算法三个雕刻师制作 n 个玩具的最小等待时间:二分答案 + 排序后贪心分配验证,附完整 C++ 代码。
3
CF 957E Novice's Mistake 题解
数据结构与算法字符串乘法与数字乘法结果相同的 (a,b) 计数:通过收紧枚举上下界让暴力可过。
4
Grafana 可视化与监控
云原生与运维Grafana 的定位、常见数据源与 Grafana + Prometheus 经典监控链路。
5
微服务之间如何传递 trace
后端开发跨服务传递的是 trace 上下文而非 tracer:HTTP header、gRPC metadata 与 MQ 消息头的标准做法。
随机文章随机推荐











