poj1990(树状数组)

题意:FJ有n头牛,排列成一条直线(不会在同一个点),给出每头牛在直线上的坐标x。另外,每头牛还有一个自己的声调v,如果两头牛(i和j)之间想要沟通的话,它们必须用同个音调max(v[i],v[j]),沟通起来消耗的能量为:max(v[i],v[j]) * 它们之间的距离。问要使所有的牛之间都能沟通(两两之间),总共需要消耗多少能量。

思路:此题和hdu3015(我前面写的,有详细解答)一种类型的,传送门:http://www.cnblogs.com/ziyi--caolu/archive/2012/12/30/2839892.html

#include<iostream>
#include<algorithm>
using namespace std;
struct node
{
	int h,d;
}s[20005];
int cmp(node &a,node &b)
{
	if(a.h>b.h)
		return 1;
	else
		return 0;
}
int c[20005],d[20005],n;
int lowbit(int x)
{
	return x&(-x);
}
void updatac(int i,int j)
{
	while(i<=20000)
	{
		c[i]+=j;
		i+=lowbit(i);
	}
}
__int64 getsumc(int x)
{
	__int64 sum=0;
	while(x>0)
	{
		sum+=c[x];
		x-=lowbit(x);
	}
	return sum;
}
void updatad(int i,int j)
{
	while(i<=20000)
	{
		d[i]+=j;
		i+=lowbit(i);
	}
}
int getsumd(int x)
{
	int sum=0;
	while(x>0)
	{
		sum+=d[x];
		x-=lowbit(x);
	}
	return sum;
}
int main()
{
	while(scanf("%d",&n)>0)
	{
		int i;
		memset(c,0,sizeof(c));
		memset(d,0,sizeof(d));
		int max=0;
		for(i=1;i<=n;i++)
		{
			scanf("%d %d",&s[i].h,&s[i].d);
			if(s[i].d>max)
				max=s[i].d;
		}
		//printf("%d\n",max);
		sort(s+1,s+1+n,cmp);
		for(i=1;i<=n;i++)
		{
			updatac(s[i].d,s[i].d);
			updatad(s[i].d,1);
			//printf("%d %d\n",s[i].h,s[i].d);
		}
		__int64 sum=0,tmp1,tmp2,m=n;
		for(i=1;i<=n;i++)
		{
			tmp1=getsumd(s[i].d-1)*s[i].d-getsumc(s[i].d-1);
			tmp2=(getsumd(max)-getsumd(s[i].d))*s[i].d-(getsumc(max)-getsumc(s[i].d));
			sum+=(tmp1-tmp2)*s[i].h;
			//printf("%I64d\t %I64d\t %I64d\t %I64d\t %I64d\n",getsumc(max),getsumc(s[i].d),getsumd(max),getsumd(s[i].d),sum);
			updatac(s[i].d,-s[i].d);
			updatad(s[i].d,-1);
		}
		printf("%I64d\n",sum);
	}
	return 0;
}

 

posted @ 2013-01-02 21:31  紫忆  阅读(470)  评论(0编辑  收藏  举报