码迷,mamicode.com
首页 > 编程语言 > 详细

学习:树状数组&线段树

时间:2018-04-06 19:30:49      阅读:152      评论:0      收藏:0      [点我收藏+]

标签:输入   暴力   分享图片   十分   包含   先来   代码   post   结果   

先上一道题目

题目描述

如题,已知一个数列,你需要进行下面两种操作:

  1. 将某一个数加上x

  2. 求出某区间每一个数的和

输入输出格式

输入格式:

第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。

第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。

接下来M行每行包含3个整数,表示一个操作,具体如下:

操作1: 格式:1 x k 含义:将第x个数加上k

操作2: 格式:2 x y 含义:输出区间[x,y]内每个数的和

输出格式:

输出包含若干行整数,即为所有操作2的结果。

输入输出样例

输入样例#1:

5 5
1 5 4 2 3
1 1 3
2 2 5
1 3 -1
1 4 2
2 1 4

输出样例#1:

14
16

说明

时空限制:1000ms,128M

数据规模:

对于30%的数据:N<=8,M<=10
对于70%的数据:N<=10000,M<=10000
对于100%的数据:N<=500000,M<=500000

想暴力过?不存在的(底层优化不敢说)。于是,我们需要一种数据结构来进行优化。

树状数组

如果我们有一个数组\(a\),我们可以构造一个数组\(C\),使\(C[i]=a[i-2^k+1]+\cdots+a[i]\)\(k\)\(i\)在二进制下末尾\(0\)的个数。

这其实是一个绝妙的想法,因为\(x\)对应的\(2^k\)是十分好求的,我们称求\(2^k\)的函数为lowbit:

inline LL lowbit(LL x)
{
    return x&(-x);
}

为什么呢?

首先,我们先来看看什么是补码:

一个数字的补码就是将该数字作比特反相运算(即反码),再将结果加1。在补码系统中,一个负数就是用其对应正数的补码来表示。
如:+8是00001000,而-8就是~8+1=11110111+1=11111000

如果\(x\)的二进制位末尾有\(k\)\(0\),那么在取时,它们都会变成\(1\),加\(1\)之后,又都变成了\(0\)。又因为\(x\)的二进制位末尾只有\(k\)\(0\),故第\(k+1\)位一定是\(1\),取反后变成\(0\),加\(1\)后,由于进位,又变成了\(1\),进位由此停止。与是,这两个数的二进制位上,除了第\(k+1\)位,其余应该都至少有一个是\(0\)\(k\)以前的为上补码一定是\(0\),可以后的位上有于取反,必定一位是\(0\),一位是\(1\))。由此可知,得到的答案是\(2^k\)

其实,C数组就是一棵树状数组。

树状数组的结构如下图所示:
技术分享图片

单点修改

代码

inline void add(LL pla,LL num)
{
    for(; pla<=n; pla+=lowbit(pla))a[pla]+=num;
}

查询

模板

typedef long long LL;

class bit
{
        LL a[500005];
        inline LL lowbit(LL x)
        {
            return x&(-x);
        }

    public:
        LL n;
        inline void add(LL pla,LL num)
        {
            for(; pla<=n; pla+=lowbit(pla))a[pla]+=num;
        }
        inline LL sum(LL pla)
        {
            LL ans=0;
            for(; pla; pla-=lowbit(pla))ans+=a[pla];
            return ans;
        }
};

学习:树状数组&线段树

标签:输入   暴力   分享图片   十分   包含   先来   代码   post   结果   

原文地址:https://www.cnblogs.com/pfypfy/p/8728414.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!