树状数组

概念 

参考博客:http://www.cnblogs.com/George1994/p/7710886.html

树状数组或者二叉索引树也称作Binary Indexed Tree,又叫做Fenwick树;它的查询和修改的时间复杂度都是log(n),空间复杂度则为O(n),这是因为树状数组通过将线性结构转化成树状结构,从而进行跳跃式扫描。通常使用在高效的计算数列的前缀和,区间和

lowbit

它通过公式来得出k,其中k就是该值从末尾开始0的个数。然后将其得出的结果加上x自身就可以得出当前节点的父亲节点的位置或者是x减去其结果就可以得出上一个父亲节点的位置。比如当前是6,二进制就是0110,k为2,那么6+2=8,而C(8)则是C(6)的父亲节点的位置;相反,6-2=4,则是C(6)的上一个父亲节点的位置。

def LOWBIT(x):
    return x & (-x)

注意:LOWBIT无法处理0的情况,因为它的结果也是0,那么最终就是一个死循环

单点修改

当我们要对最底层的值进行更新时,那么它相应的父亲节点存储的和也需要进行更新,所以修改的代码如下:

def MODIFY(x, delta):
    if x < 1:
        return
    while x <= n:
        fenwick[x] += delta
        x += LOWBIT(x)

查询

而查询的时候,则需要向前进行统计

def QUERY(x):
    result = 0
    while right > 0:
        result += fenwick[x]
        x -= LOWBIT(x)
    return result

题目:https://www.nowcoder.com/acm/contest/139/J

题意:给出n个数,求 [1,L],[R,n]这两个区间不同数的个数
其实你只要把区间扩大一倍,就是求 [R,L+n]这个区间了

#include<bits/stdc++.h>
using namespace std;
#define MAX 200005
int bit[MAX],n,q;
map<int,int>mp;
struct Query
{
    int l,r,id;
    bool operator < (const Query& a)const{
      return r<a.r;
    }
}b[MAX];
int gsum(int i)
{
    int s=0;
    while(i>0)
    {
        s+=bit[i];
        i-=i&-i;
    }
    return s;
}
void add(int i,int k)
{
    while(i<=n)
    {
        bit[i]+=k;
        i+=i&-i;
    }
}
int main()
{
    while(~scanf("%d %d",&n,&q)){
      mp.clear();
    memset(bit,0,sizeof(bit));
    vector<int>a(n*2+10),ans(q);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        a[i+n]=a[i];
    }
    n=n*2;
    for(int i=0;i<q;i++)
    {
        int l,r;
        scanf("%d %d",&l,&r);
        b[i].l=r;
        b[i].r=l+n/2;
        b[i].id=i;
    }
    sort(b,b+q);
    int pre=1;
    for(int i=0;i<q;i++)
    {
        for(int j=pre;j<=b[i].r;j++)
        {
            if(mp[a[j]])
            {
                add(mp[a[j]],-1);
            }
            add(j,1);
            mp[a[j]]=j;
        }
        pre=b[i].r+1;
      ans[b[i].id]=gsum(b[i].r)-gsum(b[i].l-1);
    }
    for(int i=0;i<q;i++)
    {
        printf("%d
",ans[i]);
    }
  }
}

【进阶——树状数组】 区间求最值

参考博客:https://www.cnblogs.com/mypride/p/5002556.html

原文地址:https://www.cnblogs.com/linhaitai/p/9553729.html