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 ;
}

数据

 

你可能感兴趣的:(USACO)