zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",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;
    }
  • 相关阅读:
    PHP常用字符串函数
    PHP 中解析 url 并得到 url 参数
    PHP中的10个实用函数
    虚拟主机知识全解
    php三种常用的加密解密算法
    Javascript中的位运算符和技巧
    ECMAScript 5中新增的数组方法
    捕捉小括号获取的内容保存在RegExp的$1 $2..属性中
    js获取浏览器窗口的大小
    关于switch的思考和总结
  • 原文地址:https://www.cnblogs.com/mltang/p/8946313.html
Copyright © 2011-2022 走看看