题意:给你一个函数f,计算∑(i = 1 to n)(j = i to n) f(i, j)。f(i, j)的定义是:取出数组中i位置到j位置的所有元素,排好序,然后把排好序的位置 * 元素 加起来。比如[7, 4, 2, 1], f(1, 4)是1 * 1 + 2 * 2 + 3 * 4 + 5 * 7;
思路:(来自PinkRabbit)我们计算每一个每一个x出现了多少次,然后加起来就是答案。我们假设一个元素y < x, 并且在x的左边,那么y对x的贡献为pos(y) * (n - pos(x) + 1)(pos(x)是x的位置),即包含y和x的区间个数。右边同理。我们用树状数组来维护.
代码:
#include <bits/stdc++.h>
#define LL long long
#define ls(x) (x << 1)
#define rs(x) ((x << 1) | 1)
#define lowbit(x) (x & (-x))
using namespace std;
const int maxn = 500010;
const LL mod = 1000000007;
LL a[maxn], p[maxn];
LL n;
class BIT {
public:
LL tr[maxn];
void add(int x, LL y) {
for (; x <= n; x += lowbit(x)) {
tr[x] += y;
tr[x] %= mod;
}
}
LL ask(int x) {
LL ans = 0;
for (; x; x -= lowbit(x)) {
ans += tr[x];
ans %= mod;
}
return ans;
}
};
BIT t1, t2;
bool cmp(LL x, LL y) {
return a[x] < a[y];
}
int main() {
scanf("%lld", &n);
for (int i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
p[i] = i;
}
LL ans = 0;
sort(p + 1, p + 1 + n, cmp);
for (int i = 1; i <= n; i++) {
LL now = p[i];
ans = (ans + (a[now] * (((n - now + 1) * now) % mod)) % mod) % mod;
ans = (ans + (a[now] * ((t1.ask(now) * (n - now + 1)) % mod + (t2.ask(n - now + 1) * now) % mod) % mod) % mod) % mod;
t1.add(now, now);
t2.add(n - now + 1, n - now + 1);
}
printf("%lld\n", ans);
}