【USACO】2004 Open MooFest 奶牛集会

来源:互联网 发布:新西兰移民 知乎 编辑:程序博客网 时间:2024/06/06 10:00

MooFest 奶牛集会


  • Description

约翰家的N头奶牛每年都会参加“哞哞大会”。哞哞大会是世界奶牛界的盛事。集会上 的活动很多,比如堆干草,跨栅栏,摸牛仔的屁股等等。当然,哞哞大叫肯定也包括在内。奶牛们的叫声很大,很多奶牛在参加多年活动之后,实际上已经失去了一部分的听力。
奶牛们已经站在了一条直线上,i号奶牛的坐标为Xi,她只能听到大于Vi的声音。每头奶 牛的位置坐标都是唯一的。
如果i号和j号奶牛想对话,则他们使用的音量为max{Vi,Vj}×|XiXj|
N头奶牛可以组合成N(N−1)/2对奶牛,假设每对奶牛都使用最小的音量在对话,请计 算所有奶牛产生的总音量是多少。

  • Input Format

第一行:单个整数:N,1≤N≤20000
第二行到第N+1行:每行有两个用空格分开的整数,Vi和Xi,1≤Vi≤20000,1≤Xi≤20000

  • Output Format

第一行:单个整数,表示最小音量之和

  • Sample Input

4
3 1
2 5
2 6
4 3

  • Sample Output

57


  • 分析

最基础的做法就是枚举两个i、j,但这显然会超时。
我们看到式子中有一个max操作,那么我们可以从v最大的开始做,每做一个就删除一个,这样子取到的max一定就是当前的v。至于x,可以用一个数据结构进行维护,这样就可以再nlogn的时间内算出答案。
注意要开 long long!!!


#include <queue>#include <stack>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int n;long long Ans;struct Data{int x,v,xid;}A[20001];struct Info{long long sum,num;}Tree[20001];inline bool cmpv(const Data&A,const Data&B){return A.v>B.v;}inline bool cmpx(const Data&A,const Data&B){return A.x<B.x;}int main(){    freopen("in.txt","r",stdin);    freopen("out.txt","w",stdout);    scanf("%d",&n);    for (int i=1;i<=n;i++) scanf("%d%d",&A[i].v,&A[i].x);     sort(A+1,A+1+n,cmpx);    for (int i=1;i<=n;i++){        A[i].xid=i;        for (int j=i;j<=n;j+=(j&(-j))) Tree[j].sum+=A[i].x,Tree[j].num++;    }    sort(A+1,A+1+n,cmpv);    for (int i=1;i<=n;i++){        long long sum=0,num=0;        for (int j=A[i].xid;j;j^=(j&(-j))) sum+=Tree[j].sum,num+=Tree[j].num;        Ans+=A[i].v*(num*A[i].x-sum); sum=-sum; num=-num;        for (int j=n;j;j^=(j&(-j))) sum+=Tree[j].sum,num+=Tree[j].num;        Ans+=A[i].v*(sum-num*A[i].x);        for (int j=A[i].xid;j<=n;j+=(j&(-j))) Tree[j].sum-=A[i].x,Tree[j].num--;    }    printf("%lld",Ans);    fclose(stdin); fclose(stdout);    return 0;}
0 0
原创粉丝点击