【每日一题】|楼兰图腾(python解法)

在完成了分配任务之后,西部 314314 来到了楼兰古城的西部。

相传很久以前这片土地上(比楼兰古城还早)生活着两个部落,一个部落崇拜尖刀(V),一个部落崇拜铁锹(),他们分别用 V 和  的形状来代表各自部落的图腾。

西部 314314 在楼兰古城的下面发现了一幅巨大的壁画,壁画上被标记出了 nn 个点,经测量发现这 nn 个点的水平位置和竖直位置是两两不同的。

西部 314314 认为这幅壁画所包含的信息与这 nn 个点的相对位置有关,因此不妨设坐标分别为 (1,y1),(2,y2),…,(n,yn)(1,y1),(2,y2),…,(n,yn),其中 y1∼yny1∼yn 是 11 到 nn 的一个排列。

西部 314314 打算研究这幅壁画中包含着多少个图腾。

如果三个点 (i,yi),(j,yj),(k,yk)(i,yi),(j,yj),(k,yk) 满足 1≤i<j<k≤n1≤i<j<k≤n 且 yi>yj,yj<ykyi>yj,yj<yk,则称这三个点构成 V 图腾;

如果三个点 (i,yi),(j,yj),(k,yk)(i,yi),(j,yj),(k,yk) 满足 1≤i<j<k≤n1≤i<j<k≤n 且 yi<yj,yj>ykyi<yj,yj>yk,则称这三个点构成  图腾;

西部 314314 想知道,这 nn 个点中两个部落图腾的数目。

因此,你需要编写一个程序来求出 V 的个数和  的个数。

输入格式

第一行一个数 nn。

第二行是 nn 个数,分别代表 y1,y2,…,yny1,y2,…,yn。

输出格式

两个数,中间用空格隔开,依次为 V 的个数和  的个数。

数据范围

对于所有数据,n≤200000n≤200000,且输出答案不会超过 int64int64。
y1∼yny1∼yn 是 11 到 nn 的一个排列。

输入样例:

5
1 5 3 2 4

输出样例:

3 4
class BitTree:
    def __init__(self, n: int):
        self.n = n
        self.tree = [0 for _ in range(n + 1)]

    def lowbit(self, x: int) -> int:
        return x & (-x)

    def add(self, i: int, val: int) -> None:
        while i <= self.n:
            self.tree[i] += val
            i += self.lowbit(i)

    def query(self, i: int) -> None:
        res = 0
        while 1 <= i:
            res += self.tree[i]
            i -= self.lowbit(i)
        return res

def main():
    n = int(input())
    nums = list(map(int, input().split()))

    BT = BitTree(n)     

    left_less = [0 for _ in range(n)]
    left_great = [0 for _ in range(n)]
    for i in range(n):
        x = nums[i]
        left_less[i] = BT.query(x - 1)
        left_great[i] = BT.query(n) - BT.query(x)
        BT.add(x, 1)

    for i in range(n + 1):
        BT.tree[i] = 0

    right_less = [0 for _ in range(n)]
    right_great = [0 for _ in range(n)]
    for i in range(n - 1, -1, -1):
        x = nums[i]
        right_less[i] = BT.query(x - 1)
        right_great[i] = BT.query(n) - BT.query(x)
        BT.add(x, 1)

    A = 0
    V = 0
    for i in range(n):
        A += left_less[i] * right_less[i]
        V += left_great[i] * right_great[i]

    print("{} {}".format(V, A))


if __name__ == "__main__":
    main()

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值