poj 1990 MooFest——树状数组

大意:很多牛站在x轴上,每个牛有一个v值;两个牛a,b交谈需要的花费为距离 * max(v(a), v(b)),求所有牛的花费和
做法:先把牛按v值排序,再做两个树状数组c1,c2,c1记录当前比牛i坐标小的牛的个数sum1,c2记录当前比牛i坐标小的牛的坐标和sum2。
 再记录当前所有的牛的坐标和alltotal
 那么对于每个牛,它对于总数的贡献为:(sum1*mow[i].x-sum2+alltotal-sum2-(i-sum1)*mow[i].x)*mow[i].v
 把每个牛算一次加起来就行了
 
 
   
a27400 1990 Accepted 840K 79MS G++ 1270B 2011-09-30 11:31:21
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 20005

using namespace std;

struct node
{
int v;
int x;
bool operator<(const node&p)const{return v<p.v;}
}mow[20010];

long long c1[20010];
long long c2[20010];

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

long long sum(long long c[],long long x)
{
long long s=0;
while(x>0)
{
s+=c[x];
x-=lowbit(x);
}
return s;
}

void update(long long c[],long long x,long long value)
{
while(x<MAXN)
{
c[x]+=value;
x+=lowbit(x);
}
}

int main(void)
{
int n;
while(scanf("%d",&n)==1)
{
memset(c1,0,sizeof(c1));
memset(c2,0,sizeof(c2));
int i;
for(i=1;i<=n;i++)
{
scanf("%d %d",&(mow[i].v),&(mow[i].x));
}
sort(mow+1,mow+1+n);
long long total=0;
long long max=0;
for(i=1;i<=n;i++)
{
if(mow[i].x>max||max==0)
max=mow[i].x;
update(c1,mow[i].x,1LL);
update(c2,mow[i].x,mow[i].x);
long long alltotal=sum(c2,max);
long long sum1=sum(c1,mow[i].x);//坐标小于等于x的个数,因为alltotal里面计算了x
long long sum2=sum(c2,mow[i].x);
total+=((long long)sum1*mow[i].x-sum2+alltotal-sum2-((long long)i-sum1)*mow[i].x)*mow[i].v;
}
printf("%lld\n",total);
}
}


你可能感兴趣的:(树状数组)