#后缀和 #排序 ## 题目大意 给我一个长度为 $N$ 的序列 $A$,第 $i$ 个数的值为 $A_i$。对于 $A_i$,你需要求出比 $A_i$ 大的数的和。 ## 思路 我们首先将数组排序,注意要记录编号,因为这题需要输出所有的答案。排完序之后,我们就从后往前做一个后缀和,因为 $A_{(i+1)}$ 一定大于等于 $A_i$。注意这里需要特殊处理一下等于的情况,使用 $l$ 记录等于了几个数,$x$ 表示等于的是几。然后统计到 $ans$ 数组就行了。 注意这题要开 `long long`,不然会 WA。 ## 代码 ```cpp #include <iostream> #include <algorithm> using namespace std; using ll = long long; const ll kMaxN = 2e5 + 5; struct Node { ll v, id; // 值和编号 } a[kMaxN]; ll p[kMaxN], ans[kMaxN], n, l, x; // p 是后缀和数组,ans 是答案数组 int main() { cin >> n; for (ll i = 1; i <= n; i++) { cin >> a[i].v, a[i].id = i; // 输入并记录编号 } sort(a + 1, a + n + 1, [](const Node &a, const Node &b) { // 排序 return a.v < b.v; // 根据值来排序 }); p[n] = 0; // 第 n 个元素没有更大的值 for (ll i = n - 1; i >= 1; i--) { // 从后往前枚举 if (a[i].v == a[i + 1].v) { // 如果是等于的情况 p[i] = p[i + 1]; // 直接赋值过来 l++, x = a[i].v; // 等于的长度加一,并记录下等于的值 } else { // 如果不是等于的情况 p[i] += p[i + 1] + a[i + 1].v + l * x; // 那么把之前的全部累加起来 l = x = 0; // 清空 } } for (ll i = 1; i <= n; i++) { ans[a[i].id] = p[i]; // 记录答案 } for (ll i = 1; i <= n; i++) { cout << ans[i] << ' '; // 输出答案 } return 0; } ```