HDU-3015. Disharmony Trees

目录

 一、题目 

        1.题目链接

        2.题意描述

        3.题目分析

二、代码解析

三、致谢


 一、题目 

Problem Description

One day Sophia finds a very big square. There are n trees in the square. They are all so tall. Sophia is very interesting in them.


She finds that trees maybe disharmony and the Disharmony Value between two trees is associated with two value called FAR and SHORT.

The FAR is defined as the following:If we rank all these trees according to their X Coordinates in ascending order.The tree with smallest X Coordinate is ranked 1th.The trees with the same X Coordinates are ranked the same. For example,if there are 5 tree with X Coordinates 3,3,1,3,4. Then their ranks may be 2,2,1,2,5. The FAR of two trees with X Coordinate ranks D1 and D2 is defined as F = abs(D1-D2).

The SHORT is defined similar to the FAR. If we rank all these trees according to their heights in ascending order,the tree with shortest height is ranked 1th.The trees with the same heights are ranked the same. For example, if there are 5 tree with heights 4,1,9,7,4. Then their ranks may be 2,1,5,4,2. The SHORT of two trees with height ranks H1 and H2 is defined as S=min(H1,H2).

Two tree’s Disharmony Value is defined as F*S. So from the definition above we can see that, if two trees’s FAR is larger , the Disharmony Value is bigger. And the Disharmony value is also associated with the shorter one of the two trees.

Now give you every tree’s X Coordinate and their height , Please tell Sophia the sum of every two trees’s Disharmony value among all trees.


Input

There are several test cases in the input

For each test case, the first line contain one integer N (2 <= N <= 100,000) N represents the number of trees.

Then following N lines, each line contain two integers : X, H (0 < X,H <=1,000,000,000 ), indicating the tree is located in Coordinates X and its height is H.


Output

For each test case output the sum of every two trees’s Disharmony value among all trees. The answer is within signed 64-bit integer.


Sample Input

2

10 100

20 200

4

10 100

50 500

20 200

20 100


Sample Output

1

13

题目链接:hdu 3015

题意描述:

        给出N棵树的坐标X和高度H,每棵树的分别按照X、H进行排名次(和我们成绩榜是一样的方式)。比如几棵树的高度分别为:3,3,1,3,4。那么这几棵树的H排名就为:2,2,1,2,5(相同高度的可以视为并列并顺沿一个位次)。下面用Xi、Hi表示第i棵树的排名。

        定义两棵树的不和谐值为Disharmony ValueFAR * SHORT。 其中FAR = | D2 - D1|, SHORT = min(H1, H2)

        题目给出n棵树,要求求出每两棵树的不和谐值并加和返回。

题目分析:

        看到这样一长串题目,不要慌,去看他的新定义项。可以看到题目中最关键的是对不和谐值的求解方式,这也决定了我们的解题方式和所使用的数据结构。不和谐值(下面我将用DV来代替)是由FAR和SHORT所决定的,FAR取决于两棵树X坐标差的绝对值,SHORT取决于高度较小的那棵树。我们不妨把题目给出顺序的序偶对按照H从大到小进行一次排列,然后得到新的一组序偶对,假设排序号之后就是(Hn, Xn), (Hn-1, Xn-1), ... , (H1, X1)。

        为什么这么做呢?假设我们要算第k棵树的DV,因为我们是按照H从大到小进行排序,所以第n棵树一直到第k+1棵树的H都是要大于第k棵树的H的,也就代表计算这几棵树与第k棵树的DV时,SHORT始终都是Hk。这样,我们只需要计算这几棵树与第k棵树的D的差值的绝对值的和,再乘上Hk就可以了。

        而如何计算前面那些树与第k棵树的D差值的绝对值呢?树状数组完美地帮我们解决了这个问题。在这个过程中,维护两个树状数组,分别用来计算第k棵树前D值小于它的树的个数以及他们的D值的和。

        有了这些分析,可以搞程序了。

二、代码解析

        首先,构造好我们按H从大到小排序的序偶对集合。这一步骤需要我们先求出每一棵树的X,H对应的排名,而这一过程有点类似我们的离散化的过程,样本代码如下:

/**
    pr[]是我们最后得到的按H从大到小排序的序偶对集合(我这里用了一个pair数组),x[], h[]是原始数组,
xx[], hh[]是对x[], h[]排序过后的副本写过离散化的小伙伴应该都可以很清楚地看懂
*/
for (int i = 0; i < n; i++)
{
    pr[i].H = lower_bound(hh, hh + n, h[i]) - hh + 1; //求H排名
    pr[i].X = lower_bound(xh, xh + n, x[i]) - xx + 1; //求X排名
}
sort(pr, pr + n, greater<pair<int, int>>()); //实际上就是对求完排名的序偶对集合按H从大到小排序(可自行百度pair自定义排序规则)

        有了序偶对集合,按部就班进行下一步。

        由上面的分析,在计算SHORT * FAR时,由于按H从大到小(倒序)排序,SHORT就是这棵树的H;FAR就是这棵树前面的树与这棵树的D的差值的绝对值之和。我们声明两个树状数组,这两个树状数组的功能是:遍历到第k棵树,分别用这两个树状数组求出这棵树前面小于这棵树的D值的树的个数(num[ k - 1 ])及他们的D值的和(sum[ k - 1 ])。

        好了,按照上面树状数组的功能,我为大家展开计算FAR的过程:

        (1)求出第k棵树前面X值小于它的树的个数num[ x - 1 ]及他们的X的和sum[ x - 1];

        (2)求出第k棵树前面X值大于它的树的个数num[ n ] - num[ x ]及他们的和sum[ n ] - num[ x ];

        (3)FAR = ( x * num[ x - 1] - sum [ x - 1 ] ) + ( sum[ n ] - num[ x ]  - x * ( num[ n ] - num[ x ] ) );

为什么要区分X值大于还是小于第k棵树的X值呢,因为只有知道了大小,我们才不会担心上式(3)出现负数的情况,也就是所谓的绝对值(实际上这里对树状数组的应用就十分巧妙了,请大家做完这道题再回来慢慢体味)。样本代码如下:

/**
    lowbit为树状数组常规操作,即x = x & (-x);
*/
void Add(int x)
{
    while(x <= n)
    {    
        sum[x] += x; //和数累加
        num[x] += 1; //个数累加
        x += lowbit(x);
    }  
}
int Sum(int x)
{    
    int ans = 0;
    while(x > 0)
    {
        ans += sum[x]; //实现求和功能
        //ans += 1;    //实现求个数功能 
        x -= lowbit(x);//以上两个功能需分开来写
    }
    return ans;
}
        

                                                                                                                                                           

三、致谢

        在此感谢@Yuhan の Blog大佬的指引,才让我理清了这道题的整个的思路。借鉴了大佬的思路,左思右想写来写去,依然十分啰嗦不得要领。这是他的原文链接,大家可前去观看:HDU 3015 Disharmony Trees(树状数组)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

落英S神剑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值