PKU-1990 [from ->USACO 2004 US Open]
分析:
20000的数据规模,暴力肯定是要超时。直观的是要求和,为了减少求和的次数,考虑运用树状数组。
发现,可以先按音量排序,然后只需要求距离,用树状数组可以很好的解决。
心得:
abs()函数使用失败!原因:不支持64int。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//528K 79MS
//abs()函数使用失败
/*
1. 将数据按音量升序排列;
2. t1[]用来求距离和。
3. t2[]用来求cow的个数。
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define NL 20001
#define LL __int64
int t2[NL];
int n, mx;
LL t1[NL];
struct vol {
int v, x;
bool operator < (const vol &a) const {
return v < a.v;
}
}vo[NL];
LL ABS(LL x)
{
if (x < 0) return -x;
return x;
}
inline int lowbit(int idx)
{
return idx&(-idx);
}
void update(int x, int c)
{
int x1 = x;
while (x <= mx) {
t1[x] += x1;
t2[x] += c;
x += lowbit(x);
}
}
LL sum(int x, LL &c)
{
LL cnt=0;
c = 0;
while (x > 0) {
cnt += t1[x];
c += t2[x];
x -= lowbit(x);
}
return cnt;
}
int main()
{
int i;
LL ans;
// freopen("in.txt", "r", stdin);
while (scanf("%d", &n) != EOF) {
mx = 0;
for (i=0; i<n; i++) {
scanf("%d%d", &vo[i].v, &vo[i].x);
if (vo[i].x > mx) mx = vo[i].x;
}
sort(vo, vo+n);
memset(t1, 0, sizeof(t1));
memset(t2, 0, sizeof(t2));
update(vo[0].x, 1);
ans = 0;
/*
k1:比cow_i位置大的距离和。
k2:比cow_i位置小的距离和。
m1:比cow_i位置大的cow的个数。
m2:比cow_i位置小的cow的个数。
*/
for (i=1; i<n; i++) {
LL k1, k2;
LL c1, c2, m1, m2;
k1 = sum(mx, c1)-sum(vo[i].x, c2);
m1 = c1-c2;
k2 = sum(vo[i].x-1, m2);
ans += (ABS(k1-m1*vo[i].x) + ABS(k2-m2*vo[i].x))*vo[i].v;
update(vo[i].x, 1);
}
printf("%I64d\n", ans);
}
return 0;
}