MooFest POJ - 1990 (树状数组)

传送门

题意:给出牛的耳聋程度和牛所在的位置,之后求出每两个牛所能听到对方的声音的和,每两个牛的计算公式为max(vi,vj)*|xi-xj|

题解:首先暴力肯定是不行的,那么可以按照牛的音量进行从小到大排序,然后维护两个树状数组,一个维护此位置之前之后的牛的个数,另一个维护此位置之前之后的牛的位置之和,之后求和即可.

附上代码:


#include<iostream>
#include<cstdio>
#include<algorithm>

using namespace std;

typedef long long ll;

const int maxn=2e4+50;

pair<int,int>cow[maxn];
int n;
ll cnt[maxn],dis[maxn];

int lowbit(int i)
{
    return i&(-i);
}

ll sum(ll *bit,int i)
{
    ll res=0;
    while(i>0){
        res+=bit[i];
        i-=lowbit(i);
    }
    return res;
}

ll sum(ll *bit,int from,int to)
{
    return sum(bit,to)-sum(bit,from);
}

void add(ll *bit,int i,ll x)
{
    while(i<=maxn){
        bit[i]+=x;
        i+=lowbit(i);
    }
}

int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d%d",&cow[i].first,&cow[i].second);
    }
    sort(cow,cow+n);
    ll ans=0;
    for(int i=0;i<n;i++){
        int v=cow[i].first,x=cow[i].second;
        int lcnt=sum(cnt,0,x),rcnt=sum(cnt,x,maxn);
        ans+=v*((x*lcnt-sum(dis,0,x))+(sum(dis,x,maxn)-rcnt*x));
        add(cnt,x,1);
        add(dis,x,x);
    }
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zhouzi2018/article/details/83239303