按题解思路,统计单点贡献
对于每个位置 x,把2x-l-r拆分成前后两部分,前部分NUM和后部分SUM可以在遍历时O(1)更新
#include <stdio.h>
using namespace std;
const int N = 1000005;
typedef unsigned int ui;
ui n, a[N];
ui suml[N], numl[N], numr[N], sumr[N], sum2[N], num2[N];
int main() {
scanf("%u", &n);
for (int i = 1; i <= n; i++) {
scanf("%u", &a[i]);
sumr[a[i]] += i;
numr[a[i]]++;
}
ui SUM = 0, NUM = 0, ans = 0;
for (int i = 1; i <= n; i++) {
numl[a[i]]++, suml[a[i]] += i;
NUM -= num2[a[i]];
num2[a[i]] = numl[a[i]] * numr[a[i]];
NUM += num2[a[i]];
SUM -= sum2[a[i]];
sum2[a[i]] = suml[a[i]] * numr[a[i]] + sumr[a[i]] * numl[a[i]];
SUM += sum2[a[i]];
ans += (NUM*i*2 - SUM) * a[i];
numr[a[i]]--, sumr[a[i]] -= i;
NUM -= num2[a[i]];
num2[a[i]] = numl[a[i]] * numr[a[i]];
NUM += num2[a[i]];
SUM -= sum2[a[i]];
sum2[a[i]] = suml[a[i]] * numr[a[i]] + sumr[a[i]] * numl[a[i]];
SUM += sum2[a[i]];
}
printf("%u\n", ans);
}