• 【洛谷P2345】奶牛集会


    题目背景

    MooFest, 2004 Open

    题目描述

    约翰的N 头奶牛每年都会参加“哞哞大会”。哞哞大会是奶牛界的盛事。集会上的活动很

    多,比如堆干草,跨栅栏,摸牛仔的屁股等等。它们参加活动时会聚在一起,第i 头奶牛的坐标为Xi,没有两头奶牛的坐标是相同的。奶牛们的叫声很大,第i 头和第j 头奶牛交流,会发出max{Vi; Vj}×|Xi − Xj | 的音量,其中Vi 和Vj 分别是第i 头和第j 头奶牛的听力。假设每对奶牛之间同时都在说话,请计算所有奶牛产生的音量之和是多少。

    输入输出格式

    输入格式:

     

    • 第一行:单个整数N,1 ≤ N ≤ 20000

    • 第二行到第N + 1 行:第i + 1 行有两个整数Vi 和Xi,1 ≤ Vi ≤ 20000; 1 ≤ Xi ≤ 20000

     

    输出格式:

     

    • 单个整数:表示所有奶牛产生的音量之和

     

    输入输出样例

    输入样例#1:
    4
    3 1
    2 5
    2 6
    4 3
    输出样例#1:
    57

    说明

    朴素O(N2)

    类似于归并排序的二分O(N logN)

    树状数组O(N logN)

    知识点

    树状数组

    分析

    朴素算法O(N2)能过去一部分点。

    题目上给的公式max{Vi; Vj}×|Xi − Xj |。

    我们可以先按照V进行从小到大排序,这样就可以排除V的干扰,也就是保证当前的Vi是最大的。

    就可以用树状数组计算前缀和了。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=20000+5;
    typedef long long ll;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    int n;
    int c1[maxn],c2[maxn];
    int mx,mn;
    struct node
    {
        int v,x;
        bool operator < (const node &j) const {
            return v<j.v;
        }
    }e[maxn];
    void update1(int x,int d)
    {while(x<=mx){c1[x]+=d;x+=x&(-x);}}
    void update2(int x,int d)
    {while(x<=mx){c2[x]+=d;x+=x&(-x);}}
    ll ask1(int x)
    {ll ans=0;while(x){ans+=c1[x];x-=x&(-x);}return ans;}
    ll ask2(int x)
    {ll ans=0;while(x){ans+=c2[x];x-=x&(-x);}return ans;}
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++)
        {
            e[i].v=read();e[i].x=read();
            mx=max(mx,e[i].x);
        }
        sort(e+1,e+n+1);
        ll ans=0;
        for(int i=1;i<=n;i++)
        {
            int x=e[i].x,v=e[i].v;
            ll num1,num2,sum1,sum2;
            num1=ask1(x-1);sum1=ask2(x-1);
            num2=ask1(mx)-ask1(x);
            sum2=ask2(mx)-ask2(x);
            ans+=v*(sum2-x*num2+x*num1-sum1);
            update1(x,1);
            update2(x,x);
        }
        printf("%lld
    ",ans);
        return 0;
    }
    

      

    欢迎转载,转载请注明出处!
  • 相关阅读:
    TVB西游记-观音的眼泪化作金河送唐僧回长安
    天下没有免费的午餐是什么意思
    什么样的经历、体验或者行为等能彻底的改变一个人
    看人先看什么
    python字符串中查找指定子字符串
    字符串的分隔及连接
    流媒体服务器音视频直播平台的开发为什么需要CDN?
    微信公众号小程序如何做流媒体视频直播?
    搭建专属于自己的视频流媒体直播/点播平台都需要注意哪些事项?
    音视频流媒体服务器的虚拟直播推流失败断流无法播放如何解决?
  • 原文地址:https://www.cnblogs.com/huihao/p/7327726.html
Copyright © 2020-2023  润新知