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;

}

 

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