POJ1990 - MooFest

题目大意

给定N对二元组(x1,y1),(x2,y2),(x3,y3)…(xn,yn).每两个二元组之间(假设分别为i和j,i!=j)将会产生一个值ans(i,j)=max(xi,xj)*|yi-yj|,计算出sigma(ans(i,j))(1<=i,j<=n,i!=j)

题解

我们可以先对x值按升序排序,之后就是用两个树状数组进行维护了,公式推导过程不知道怎么讲。。。直接看代码好了。。。

#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

#define MAXN 20005

using namespace std;

typedef struct

{

    int v;

    int x;

} NODE;

NODE a[MAXN];

int n;

long long c[MAXN],b[MAXN];

int lowbit(int x)

{

    return x&-x;

}

int sum(long long p[],int x)

{

    int ret=0;

    while(x>0)

    {

        ret+=p[x];

        x-=lowbit(x);

    }

    return ret;

}

void add(long long p[],int x,int d)

{

    while(x<=MAXN)

    {

        p[x]+=d;

        x+=lowbit(x);

    }

}

bool cmp(NODE a,NODE b)

{

    return a.v<b.v;

}

int main(void)

{

    long long ans=0,total=0,cnt,sums;

    int i;

    scanf("%d",&n);

    for(i=1; i<=n; i++)

        scanf("%d%d",&a[i].v,&a[i].x);

    sort(a+1,a+n+1,cmp);

    memset(c,0,sizeof(c));

    memset(b,0,sizeof(b));

    for(i=1; i<=n; i++)

    {

        cnt=sum(b,a[i].x);

        sums=sum(c,a[i].x);

        ans+=a[i].v*(total-2*cnt+(2*sums-i+1)*a[i].x);

        add(b,a[i].x,a[i].x);

        add(c,a[i].x,1);

        total+=a[i].x;

    }

    cout<<ans<<endl;

    return 0;

}

你可能感兴趣的:(poj)