您的位置:首页 > Web前端

poi 1990 MooFest(树状数组题目,转换成两个树状数组来做)较难的题目****

2014-03-07 20:45 411 查看
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、题目:

MooFest

Time Limit: 1000MSMemory Limit: 30000K
Total Submissions: 4791Accepted: 2009
Description
Every year, Farmer John's N (1 <= N <= 20,000) cows attend "MooFest",a social gathering of cows from around the world. MooFest involves a variety of events including haybale stacking, fence jumping, pin the tail on the farmer,
and of course, mooing. When the cows all stand in line for a particular event, they moo so loudly that the roar is practically deafening. After participating in this event year after year, some of the cows have in fact lost a bit of their hearing.

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
* Line 1: A single integer, N

* 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
* Line 1: A single line with a single integer that is the sum of all the volumes of the conversing cows.

Sample Input
4
3 1
2 5
2 6
4 3

Sample Output
57

Source
USACO 2004 U S Open
5、AC代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 20005
__int64 cnum
;//cnum[i]以i声调为下标比当前牛小的牛的数量
__int64 dnum
;//dnum[i]表示以声调为下标,距离比当前小的牛的距离和(到原点的距离)
struct node
{
int w;
int x;
}a
;
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
;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: