1、http://poj.org/problem?id=1990
2、题目大意:
题意:FJ有n头牛,排列成一条直线(不会在同一个点),给出每头牛在直线上的坐标x。另外,每头牛还有一个自己的声调w,如果两头牛(i和j)之间想要沟通的话,它们必须用同个音调max(w[i],w[j]),沟通起来消耗的能量为:max(w[i],w[j]) * 它们之间的距离。问要使所有的牛之间都能沟通(两两之间),总共需要消耗多少能量。
3.题目分析:
思路:树状数组。很好的一道题。把牛按x升序排列,然后将题目中的x考虑成从左到右求比自己当前声音小的牛的个数以及距离求出总共消耗的能量来,再逆序求比自己大的牛的个数及距离,这样就能保证是两两都能听到也就是保证了他们之间的正常沟通问题
1:把沟通分成向左和向右,向左就是:w[右] > w[左],它们之间取右边牛的声调。
2:先求向左的总能量:运用2个树状数组,都以牛的声调做下标,cnum[]用于求某个声调范围内牛的数量,dnum[]用于求某个声调范围内牛的总距离(与起点0的总距离),这对于当前的牛(x,v)来说,用它的音调向左沟通消耗的总能量则为:w* 左边声调比它小的牛和它的距离差之和(sum(w-1, cum)* sum(v-1,dnum))。
3:相同的道理求出向右的总能量。
4、题目:
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 4791 | Accepted: 2009 |
Description
Each cow i has an associated "hearing" threshold v(i) (in the range 1..20,000). If a cow moos to cow i, she must use a volume of at least v(i) times the distance between the two cows in order to be heard by cow i. If two cows i and j wish to converse, they must speak at a volume level equal to the distance between them times max(v(i),v(j)).
Suppose each of the N cows is standing in a straight line (each cow at some unique x coordinate in the range 1..20,000), and every pair of cows is carrying on a conversation using the smallest possible volume.
Compute the sum of all the volumes produced by all N(N-1)/2 pairs of mooing cows.
Input
* Lines 2..N+1: Two integers: the volume threshold and x coordinate for a cow. Line 2 represents the first cow; line 3 represents the second cow; and so on. No two cows will stand at the same location.
Output
Sample Input
4 3 1 2 5 2 6 4 3
Sample Output
57
Source
5、AC代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 20005
__int64 cnum[N];//cnum[i]以i声调为下标比当前牛小的牛的数量
__int64 dnum[N];//dnum[i]表示以声调为下标,距离比当前小的牛的距离和(到原点的距离)
struct node
{
int w;
int x;
}a[N];
int cmp(node a,node b)
{
return a.x<b.x;
}
int lowbit(int i)
{
return i&(-i);
}
void update(int x,int v,__int64 *c)
{
for(int i=x;i<=N;i+=lowbit(i))
{
c[i]+=v;
}
}
__int64 sum(int x,__int64 *c)
{
__int64 sum=0;
for(int i=x;i>0;i-=lowbit(i))
{
sum+=c[i];
}
return sum;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
__int64 ans=0;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&a[i].w,&a[i].x);
}
sort(a+1,a+n+1,cmp);
__int64 cowNum=0;
__int64 cowDist=0;
memset(cnum,0,sizeof(cnum));
memset(dnum,0,sizeof(dnum));
for(int i=1;i<=n;i++)
{
cowNum=sum(a[i].w-1,cnum);
cowDist=sum(a[i].w-1,dnum);
ans+=(a[i].x*cowNum-cowDist)*a[i].w;
update(a[i].w,1,cnum);
update(a[i].w,a[i].x,dnum);
}
memset(cnum,0,sizeof(cnum));
memset(dnum,0,sizeof(dnum));
for(int i=n;i>=1;i--)
{
cowNum=sum(a[i].w,cnum);
cowDist=sum(a[i].w,dnum);
ans+=(cowDist-a[i].x*cowNum)*a[i].w;
update(a[i].w,1,cnum);
update(a[i].w,a[i].x,dnum);
}
printf("%I64d\n",ans);
}
return 0;
}
附自己开始用for循环做错的代码,其实这么大的数据for一般都是不正确的
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 20005
struct node
{
int v;
int x;
}a[N];
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;i++)
{
scanf("%d%d",&a[i].v,&a[i].x);
}
int sum=0;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
int m=max(a[i].v,a[j].v);
sum+=abs(a[i].x-a[j].x)*m;
}
}
printf("%d\n",sum);
}
return 0;
}