題目鏈接:http://poj.org/problem?id=1990

/**//*
題意:
約翰農夫有N(N <= 20000)頭牛,每頭牛有一個權值Vi,他將它們排成一排,
牛i和牛j的閾值是 兩者的距離差*max(Vi, Vj),現在給出每頭牛的權值和它的
位置,求所有兩頭牛之間的閾值之和。

題解:
樹狀數組

思路:
我們準備兩個樹狀數組,以每頭牛的位置作為樹狀數組的下標,其中一個用
來表示當前位置的牛的位置的值,另一個則記錄當前位置牛的個數,然后對所有
牛以Vi為關鍵字進行遞增排序。
接下來對每頭牛進行一次線掃,首先統計比當前這頭牛的位置小的和大的牛
的數目和位置和,然后做差求出以當前牛的權值為最大值的閾值總和。之后將這
頭牛的數量和位置插入到樹狀數組中進行更新。
*/

#include <iostream>
#include <algorithm>

using namespace std;

#define maxn 20010
#define ll __int64


struct point
{
int V;
int pos;
}pt[maxn];

ll c[2][maxn];
int n, Max;


ll ABS(ll v)
{
return v < 0 ? -v : v;
}


int cmp(point a, point b)
{
return a.V < b.V;
}


int lowbit(int x)
{
return x & (-x);
}


void add(int idx, int pos, int v)
{

while(pos <= Max)
{
c[idx][pos] += v;
pos += lowbit(pos);
}
}


ll sum(int idx, int pos)
{
ll s = 0;

while(pos > 0)
{
s += c[idx][pos];
pos -= lowbit(pos);
}
return s;
}



int main()
{
int i;

while(scanf("%d", &n) != EOF)
{
Max = 0;

for(i = 0; i < n; i++)
{
scanf("%d %d", &pt[i].V, &pt[i].pos);
if(pt[i].pos > Max)
Max = pt[i].pos;
}

for(i = 1; i <= Max; i++)
c[0][i] = c[1][i] = 0;
sort(pt, pt + n, cmp);

ll ans = 0;

for(i = 0; i < n; i++)
{
ans += ABS((sum(0, Max) - sum(0, pt[i].pos)
- (sum(1, Max) - sum(1, pt[i].pos)) * pt[i].pos)) * pt[i].V;

ans += ABS((sum(0, pt[i].pos)
- sum(1, pt[i].pos) * pt[i].pos)) * pt[i].V;

add(0, pt[i].pos, pt[i].pos);
add(1, pt[i].pos, 1);
}
printf("%I64d\n", ans);
}
return 0;
}