Fall with Trees

本文介绍了一种计算二叉树宽度变化规律及其在求取凸包面积中的应用,通过等比数列求和技巧,给出了面积的公式。解决了一个涉及树结构、等比数列和面积计算的实际问题。

题目链接

Δ = x r s o n − x l s o n , h = y r o o t − y l s o n \Delta=xrson-xlson,h=yroot-ylson Δ=xrsonxlson,h=yrootylson,第 i i i层的宽度为 l e n i len_i leni,有$len_2 =len_1+\Delta,len_3 =len_2+{\Delta \over 2},len_4=len_3+{\Delta \over 4} $ ,即有 l e n k = l e n 1 + Δ + Δ 2 + Δ 4 + . . . + Δ ( k − 1 ) len_k=len_1+\Delta+{\Delta \over 2}+{\Delta \over 4}+...+{\Delta \over (k-1)} lenk=len1+Δ+2Δ+4Δ+...+(k1)Δ,后方显然是一个以 Δ \Delta Δ为首项, 1 2 1 \over 2 21为公比的等比数列, l e n 1 = 0 len1=0 len1=0,则 l e n k = Δ ∗ ( 1 − ( 1 2 ) k − 1 ) ( 1 − 1 2 ) = 2 ∗ Δ − 2 2 − k Δ len_k = {\Delta*(1-({1 \over 2})^{k-1}) \over (1-{1\over 2})}=2*\Delta-2^{2-k}\Delta lenk=(121)Δ(1(21)k1)=2Δ22kΔ,比较显然的是凸包由树的最左树链和最右树链及所有叶子结点构成的,它的面积为相邻层构成的图形的面积之和,则有 S = 1 2 ∗ h ( l e n 1 + l e n 2 + l e n 2 + l e n 3 + l e n 3 + l e n 4 + . . . + l e n k − 1 + l e n k ) {S = {1 \over 2}*h({len_1+len_2+len_2+len_3+len_3+len_4+...+len_{k-1}+len_k})} S=21h(len1+len2+len2+len3+len3+len4+...+lenk1+lenk)
即有 S = 1 2 ∗ h ( l e n 1 + 2 ∗ l e n 2 + 2 ∗ l e n 3 + . . . + 2 ∗ l e n k − 1 + l e n k ) S={1 \over 2}*h({len_1+2*len_2+2*len_3+...+2*len_{k-1}+len_k}) S=21h(len1+2len2+2len3+...+2lenk1+lenk), l e n 1 = 0 len_1=0 len1=0,
化简可得: S = h ∗ ( l e n 2 + l e n 3 + l e n 4 . . . + l e n k ) + l e n k ∗ h 2 = h ∗ ( 2 ∗ Δ − 2 2 − 2 Δ + 2 ∗ Δ − 2 1 − k Δ + . . . + 2 ∗ Δ − 2 3 − k ) + h ∗ 2 Δ − 2 2 − k 2 S=h*(len_2+len_3+len_4...+len_k)+{len_k*h \over 2}=h*({2*\Delta-2^{2-2}\Delta+2*\Delta-2^{1-k}\Delta}+...+2*\Delta-2^{3-k})+{h*{2\Delta-2^{2-k}\over 2}} S=h(len2+len3+len4...+lenk)+2lenkh=h(2Δ222Δ+2Δ21kΔ+...+2Δ23k)+h22Δ22k
后面的减数也构成一个以 Δ \Delta Δ为首项, 1 2 1 \over 2 21为公比的等比数列,求和化简可得: S = h ∗ ( ( k − 2 ) Δ − ( 2 ∗ Δ − 2 3 − k Δ ) ) + h ∗ 2 Δ − 2 2 − k 2 S=h*((k-2)\Delta-(2*\Delta-2^{3-k}\Delta))+{h*2\Delta-2^{2-k}\over 2} S=h((k2)Δ(2Δ23kΔ))+2h2Δ22k

数据范围 T < = 2 e 5 , k < = 1 e 4 T<=2e^5,k<=1e^4 T<=2e5,k<=1e4,且无模数,暴力算 2 x 2^x 2x显然不可行,此题精度要求不算高,因此当 k k k够大时,认为 2 − x 2^{-x} 2x为0

AcCode:

#include <iostream>
#include <algorithm>
#include <stack>
#include <iomanip>
#include <cstdio>

#define SYNC std::ios::sync_with_stdio(false)
#define CIN std::cin.tie(0);
#define COUT std::cout.tie(0);

double dv[52];

signed main() {
    int t; scanf("%d", &t);
    dv[0] = 1;
    for (int i = 1; i <= 50; i++) dv[i] = dv[i - 1] * 2;
    while (t--) {
        int k; scanf("%d", &k);
        int xroot, yroot, xlson, ylson, xrson, yrson; scanf("%d %d %d %d %d %d", &xroot, &yroot, &xlson, &ylson, &xrson, &yrson);
        double h = 1.0 * yroot - ylson, q = 1.0 * xrson - xlson;
        double ans = 0;
        if (k == 2) {
            ans = h * q / 2.0;
            printf("%.3lf\n", ans);
            continue;
        }
        double add1 = (k - 2.0) * 2.0 * q;
        double sub1 = 2.0 * q - ((k < 50) ? q / dv[k - 3] : 0);
        add1 = h * (add1 - sub1);
        double add2 = q * h;
        double sub3 = (k < 50) ? q * h / dv[k - 1] : 0;
        ans = add1 + add2 - sub3;
        printf("%.3lf\n", ans);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值