HDU3015 Disharmony Trees

题目大意

和POJ1990是一样的,只是把max改成min了。。。

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

题解

需要对x,y进行离散,然后把y值按降序排序,之后的做法和POJ3015完全是一样的。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 100005
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 cmp1(NODE a,NODE b)
{
    return a.x<b.x;
}
bool cmp2(NODE a,NODE b)
{
    return a.v>b.v;
}
int main(void)
{
    long long ans,total,cnt,sums;
    int pre,prev;
    int i;
    while(scanf("%d",&n)!=EOF)
    {
        ans=0;
        total=0;
        for(i=1; i<=n; i++)
            scanf("%d%d",&a[i].x,&a[i].v);
        sort(a+1,a+n+1,cmp1);
        pre=-1;
        prev=0;
        for(i=1; i<=n; i++)
            if(pre!=a[i].x)
            {
                pre=a[i].x;
                a[i].x=i;
                prev=i;
            }
            else
                a[i].x=prev;
        sort(a+1,a+n+1,cmp2);
        pre=-1;
        prev=0;
        for(i=n; i>=1; i--)
            if(pre!=a[i].v)
            {
                pre=a[i].v;
                a[i].v=n-i+1;
                prev=n-i+1;
            }
            else
                a[i].v=prev;
        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/3036929.html