题目链接: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;
}