【poj 1990】MooFest(树状数组)

来源:互联网 发布:淘宝奥巴狗游戏 编辑:程序博客网 时间:2024/05/29 12:18

传送门biu~
题目大意:一群牛站成一条直线,第i头牛听见别人的讲话,别人的音量必须大于v[i]。两头牛i、j必须用同一个声音max(v[i],v[j])交流。消耗的能量为 声音大小*他们之间的距离。现在有n头牛,给定n头牛的v[i]和坐标,求他们之间两两交流所需要的能量和。
思路:把每头牛按v值大小排序。逐一加入时,第i头牛与第1~(i-1)头牛交流的声音大小一定是v[i]。这样就用树状数组numtree维护有多少头牛,用loctree维护牛的坐标和,用tot维护当前已加入的所有的牛的坐标和。
所以对于牛i,他前面有num头牛,这些牛的坐标和为loc,第i头牛的坐标为xi,声音v值为vi。那么它和比它坐标小的牛之间的坐标差front=num*xi-loc;它和比他坐标大的牛之间的坐标差back=(tot-loc-xi)-xi(i-num-1)。
最后让ans的值加上v[i]*(front+back)就可以了。

#include<bits/stdc++.h>#define lowbit(x) (x&(-x))#define MAXN 20005#define ll long longusing namespace std;struct COW{    int v,x;}a[MAXN];inline bool cmp(COW a,COW b){return a.v<b.v;}ll numtree[MAXN],loctree[MAXN],n;int Nmax;inline void add(ll *a,int x,int num){    while(x<=Nmax)    {        a[x]+=num;        x+=lowbit(x);    }}inline ll search(ll *a,int x){    ll re=0;    while(x)    {        re+=a[x];        x-=lowbit(x);    }    return re;}int main(){    while(~scanf("%d",&n))    {        ll ans=0,tot=0;        memset(numtree,0,sizeof(numtree));        memset(loctree,0,sizeof(loctree));        Nmax=0;        for(int i=1;i<=n;++i)        {            scanf("%d%d",&a[i].v,&a[i].x);            Nmax=max(a[i].x,Nmax);        }           sort(a+1,a+n+1,cmp);        for(int i=1;i<=n;++i)        {            add(numtree,a[i].x,1);            add(loctree,a[i].x,a[i].x);            tot+=a[i].x;            ll num=search(numtree,a[i].x-1);            ll loc=search(loctree,a[i].x-1);            ll front=num*a[i].x-loc;            ll back=(tot-loc-a[i].x)-a[i].x*(i-num-1);            ans+=a[i].v*(front+back);        }        printf("%lld\n",ans);    }    return 0;}
阅读全文
0 0