POJ 1990

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_40924940/article/details/83625327

这是接触的第一道树状数组题。。想了比较长的时间。。最后网上找的一下思路。。是道很好的题。。以后要复习一下。。

题目大意:

        有 N 头牛,每头牛位于 第 Xi 位 且只有叫它声音高于 Vi 他才听得见,而牛之间交流消耗的能量 譬如第 i 头和第 j 头交流 消耗能量为 max(vi,vj)*( | xi - xj | )

首先 我们要优先去看那些失聪程度大的牛,比如当前为 第 K 头,那么当任意牛 i 的Vi 小于 Vk 时,我们以 Vk 为准,所以可以先按 V 排序,那么我们只需要在对牛遍历是 看距离就可以了

接下来公式为 \sum (Xi - Xj)*vi 就可以了 由于数据原因。本题直接暴力去算会超时,我们这时候便可以用 BIT 优化 最终解决。

因为排完序之后 完全无需去看 v 只需要最后计算的时候 把它乘上即可,我们开两个 树状数组 一个维护 比当前牛距离小的牛的个数,另一个维护比当前牛距离小的牛的坐标。

至于计算公式,我们可以用 sum( xi ) 求出比当前牛位置小的牛的位置, 可以用 sum( maxn )求出加入数组内所有牛的坐标和,经过计算 我们还知道目前放入数组一共有几头牛,那么根据公式进行加减便可以求出了

以下为AC 代码(这道题真的不适合刚刚学树状数组的人去做)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
 
using namespace std;
 
#define ll long long
 
struct node
{
    ll f,x;
} s[20010];

bool cmp(node a,node b)
{
    return a.f<b.f;
} 

int n;
ll c1[20010],c2[20010];
 
ll lowbit(ll k)
{
    return k&(-k);//二进制末尾的 1 的十进制数
}
 
void add1(ll k,ll num)
{
    while (k<20010)
    {
        c1[k]+=num;
        k+=lowbit(k);
    }
}
 
void add2(ll k,ll num)
{
    while (k<20010)
    {
        c2[k]+=num;
        k+=lowbit(k);
    }
}
 
ll sum1(ll k)
{
    ll sm=0;
    while (k)
    {
        sm+=c1[k];
        k-=lowbit(k);
    }
    return sm;
}
 
ll sum2(ll k)
{
    ll sm=0;
    while (k)
    {
        sm+=c2[k];
        k-=lowbit(k);
    }
    return sm;
}
 
int main()
{
    while (~scanf("%d",&n))
    {
        for (int i=1; i<=n; i++)
        {
            scanf("%lld%lld",&s[i].f,&s[i].x);
        }
        memset(c1,0,sizeof(c1));
        memset(c2,0,sizeof(c2));
        sort(s+1,s+n+1,cmp);
        ll ans=0;
        for (int i=1; i<=n; i++)
        {
            add1(s[i].x,1);
            add2(s[i].x,s[i].x);//维护更新两个数组
            ll nn=sum1(s[i].x);//个数
            ll sss=sum2(s[i].x);//坐标
            ans+=(nn*s[i].x-sss)*s[i].f;//得到的是在当前x前面所有坐标小于他的牛
            ll nnn=i-nn;
            ll ss=sum2(20000)-sss;//总共的减去比较近的等于比较远的
            ans+=(ss-s[i].x*nnn)*s[i].f;//在他前面的比他坐标值大的x
 
        }
        printf ("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40924940/article/details/83625327
POJ