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;
}
原文地址:https://www.cnblogs.com/zjbztianya/p/3036928.html