POJ 1990 MooFest
Posted -ackerman
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 1990 MooFest相关的知识,希望对你有一定的参考价值。
每年,农夫约翰的N(1 <= N <= 20,000)只牛会参加“MooFest”,一个来自世界各地的牛的社交聚会。 MooFest有许多活动,包括干草堆积,篱笆跳跃,把尾巴钉在农夫的身上...当奶牛都站在同一个地方排队,他们会大声喊叫,吼声几乎震耳欲聋。事实上,每年参加了这个活动后,一些奶牛已经失去了部分听力。
每个奶牛具有耳背值v(i)(在1..20,000的范围内)。如果一头牛向牛i吼叫,她必须使用至少是两头母牛之间距离的v(i)倍的声音,以便被牛i听到。如果两个奶牛i和j想要交谈,她们必须以等于她们之间的距离乘以max(v(i),v(j))的音量说话。
假设N头奶牛中的每头奶牛都站在直线上(每头奶牛在1..20,000范围内的某个独特x坐标),每对奶牛都使用尽可能小的声音进行谈话。
计算所有N(N-1)/ 2对正在说话的奶牛产生的所有声音的总和。
Input
*第1行:单个整数,N
*第2到N + 1行:两个整数:牛的耳背值v和x坐标。第2行代表第一头牛;第3行表示第二头牛;等等。没有两头牛会站在同一个位置。
Output
*第1行:仅含单个整数,表示所有牛互相吼叫的所有声音的总和。
Sample Input
4
3 1
2 5
2 6
4 3
Sample Output
57
思路:当两头牛进行计算时,用到的是V值大的牛。所以先按照V值从大到小排序,当计算某头牛时,只考虑V值比它小的那些牛。我们用两个树状数组分别表示牛的坐标之和及牛的数量之和(以坐标作为数组下标)。那么考虑牛i时(按V从大到小排序后),设坐标值比它小的那些牛的数目为num1、坐标之和为sum1,坐标值比它大的那些牛的数目为num2、坐标之和为sum2,那么对该牛而言(设坐标为X,体力值为V),所贡献的答案为V * ( X*num1-sum1 + sum2-X*num2 )。
#include <stdio.h> #include <algorithm> #include <iostream> #include <stdlib.h> #include <string> #include <string.h> #include <math.h> #include <vector> #include <queue> #include <stack> #include <map> #include <set> #define INF 0x3f3f3f3f #define LL long long using namespace std; const int MAXN = 2e5+5; struct Node int x; int val; ; int c1[MAXN],c2[MAXN]; Node a[MAXN]; int n; bool cmp(Node a,Node b) return a.val>b.val; int lowbit(int x) return x & (-x); void updata(int a[],int x,int v) while (x<MAXN) a[x] += v; x += lowbit(x); int getsum(int a[],int x) int res = 0; while (x) res += a[x]; x -= lowbit(x); return res; int main() scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d%d",&a[i].val,&a[i].x); updata(c1,a[i].x,a[i].x); updata(c2,a[i].x,1); sort(a+1,a+1+n,cmp); LL ans = 0; for (int i=1;i<=n;i++) updata(c1,a[i].x,-a[i].x); updata(c2,a[i].x,-1); int sum1 = getsum(c1,a[i].x); int sum2 = getsum(c1,MAXN)-sum1; int num1 = getsum(c2,a[i].x); int num2 = getsum(c2,MAXN)-num1; ans += (LL)(abs(a[i].x*num1-sum1)+abs(sum2-a[i].x*num2))*a[i].val; printf("%lld\n",ans); return 0;
以上是关于POJ 1990 MooFest的主要内容,如果未能解决你的问题,请参考以下文章