hdu 3015

这个题给你一堆树,每棵树的位置x和高度h都给你

f[i]代表这棵树的位置排名,s[i]代表这棵树的高度排名

问你任意两棵树的(f[i] - f[j])*min(s[i],s[j])和

(f[i]-f[i-1])*min(s[i],s[i-1]) + (f[i]-f[i-2])*min(s[i],s[i-2])

首先看看暴力,肯定过不去,毕竟n2复杂度

看这个式子,其实比s[i]大的那么多项都能合并

合并成 ((f[i] - f[i-1])+ (f[i] - f[i-2]) +.....)*s[i]

所以只要在尽快的时间内求出(f[i] - f[i-1] + f[i] - f[i-2] ........)

f[i]是第i棵数的坐标排名

基本就是区间求和     求出小于f[i]的有多棵树   求出小于f[i]的树的坐标和

创建两个树状数组,非别维护坐标和 and 前面树的数量

复杂度就是nlogn了

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1e6+5;
struct node
{
    long long x,h;
    int p1,p2;
} arr[maxn];
int c[maxn];
int d[maxn];
int n;
bool cmp2(node a,node b);
bool cmp1(node a,node b);
long long getsumd(int i);
long long getsumc(int i);
void addc(long long i,long long j);
void addd(long long i,long long j);
int main()
{
    int m,i,j,k;
    while (scanf("%d",&n) != EOF)
    {
        memset(c, 0, sizeof(c));
        memset(d, 0, sizeof(d));
        for(i=1;i<=n;++i)
            scanf("%lld%lld",&arr[i].x,&arr[i].h);
        sort(arr+1,arr+n+1,cmp1);
        arr[1].p1 = 1;
        for(i=2;i<=n;++i)
        {
            if(arr[i].x == arr[i-1].x)
                arr[i].p1 = arr[i-1].p1;
            else
                arr[i].p1 = i;
        }
        sort(arr+1,arr+1+n,cmp2);
        arr[1].p2 = 1;
        for(i=2;i<=n;++i)
        {
            if(arr[i].h == arr[i-1].h)
                arr[i].p2 = arr[i-1].p2;
            else
                arr[i].p2 = i;
        }
        for(i=1;i<=n;++i)
        {
            addc(arr[i].p1,arr[i].p1);
            addd(arr[i].p1, 1);
        }
        long long maxnn=0;
        for(i=1;i<=n;++i)
        {
            long long k1 = (getsumd(arr[i].p1))*arr[i].p1 - getsumc(arr[i].p1);
            //printf("%lld  %lld\n",getsumc(n)-getsumc(arr[i].p1),(getsumd(n) - getsumd(arr[i].p1))*arr[i].p1);
            k1 += (getsumc(n)-getsumc(arr[i].p1)) - (getsumd(n) - getsumd(arr[i].p1))*arr[i].p1;
            
            maxnn+=k1*arr[i].p2;
            addc(arr[i].p1, -arr[i].p1);
            addd(arr[i].p1, -1);
        }
        printf("%lld\n",maxnn);
    }
}
long long lowbit(long long k)
{
    return k&(-k);
}
void addc(long long i,long long  j)
{
    while(i<=n)
    {
        c[i]+=j;
        i+=lowbit(i);
    }
}
void addd(long long i,long long j)
{
    while(i<=n)
    {
        d[i]+=j;
        i+=lowbit(i);
    }
}
long long getsumc(int i)
{
    long long su = 0;
    while(i>0)
    {
        su+=c[i];
        i-=lowbit(i);
    }
    return su;
}
long long getsumd(int i)
{
    long long su = 0;
    while(i>0)
    {
        su+=d[i];
        i-=lowbit(i);
    }
    return su;
}
bool cmp1(node a,node b)
{
    if(a.x<b.x)
        return true;
    return false;
}
bool cmp2(node a,node b)
{
    if(a.h<b.h)
        return true;
    return false;
}

猜你喜欢

转载自www.cnblogs.com/mltang/p/8946313.html