51NOD 1712 - 區間求和
阿新 • • 發佈:2018-04-26
scanf cpp ace space const highlight stdio.h nod pac
按題解思路,統計單點貢獻
對於每個位置 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); }
51NOD 1712 - 區間求和