PKU-1990 [from ->USACO 2004 US Open]

MooFest

分析:

20000的数据规模,暴力肯定是要超时。直观的是要求和,为了减少求和的次数,考虑运用树状数组。

发现,可以先按音量排序,然后只需要求距离,用树状数组可以很好的解决。

心得:

abs()函数使用失败!原因:不支持64int。

 

代码
//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;
}

数据

 

posted @ 2010-08-13 20:59  superbin  阅读(475)  评论(0编辑  收藏  举报