題意就是有N頭牛,每頭牛都有一個座標和聲調值(x, v),兩頭牛之間通訊要花費的能量是他們的距離乘以最大的一個音調值,現在要任意兩頭牛之間都相互連訊一次,求總共需要花費多少能量?
顯然總共有n*(n+1)/2條,我們可以用樹狀數組儲存,樹狀數組很適合求區間的和,我們只需要求出某頭牛左右兩邊分別有多少頭牛比它的音調小,且他們的座標和,這樣我們就能求出這頭牛到其他牛之間的距離和了,因為它的音調值已知且在這先中最大,然後這要求出一頭牛與其他比他小的通訊花費的能量了,然後以此求出其他的。這樣計算出了它小的,遍曆一遍後必然每頭牛之間都有裡通訊。
#include<iostream>#include<algorithm>#define lowbit(x) (x&(-x))using namespace std;const int MAX = 20005; struct data{ int x, w;}cow[MAX];int arNum[MAX], arDis[MAX]; bool cmp(data a, data b){ return a.x < b.x;} void add(int i, int *ar, int w){ while(i <= MAX-1){ ar[i] += w; i += lowbit(i); }} __int64 sum(int i, int *ar){ __int64 ans = 0; while(i > 0){ ans += ar[i]; i -= lowbit(i); } return ans;} int main(){ int n, i; __int64 preNum, preDis; scanf("%d", &n); for(i = 0; i < n; i ++) scanf("%d%d", &cow[i].w, &cow[i].x); sort(cow, cow + n, cmp); __int64 ans = 0; memset(arNum, 0, sizeof(arNum)); // 求向左的總能量。 memset(arDis, 0, sizeof(arDis)); for(i = 0; i < n; i ++){ preNum = sum(cow[i].w-1, arNum); preDis = sum(cow[i].w-1, arDis); ans += (preNum * cow[i].x - preDis) * cow[i].w; add(cow[i].w, arNum, 1); add(cow[i].w, arDis, cow[i].x); } memset(arNum, 0, sizeof(arNum)); // 求向右的總能量。 memset(arDis, 0, sizeof(arDis)); for(i = n-1; i >= 0; i --){ preNum = sum(cow[i].w, arNum); // 這裡不要用w-1,考慮了聲調相等的情況。 preDis = sum(cow[i].w, arDis); ans += (preDis - preNum * cow[i].x) * cow[i].w; add(cow[i].w, arNum, 1); add(cow[i].w, arDis, cow[i].x); } printf("%I64d\n", ans); return 0;}