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的主要内容,如果未能解决你的问题,请参考以下文章

POJ 1990 MooFest

POJ 1990 MooFest

MooFest POJ - 1990 树状数组

MooFest POJ - 1990 (树状数组)

POJ 1990 MooFest

●POJ 1990 MooFest