by zyq / 2014 / 7

树状数组何其牛逼只能这么形容啊。

首先,网上好多对树状数组基础知识讲解的在这就不细讲了。可以参考  

 http://blog.csdn.net/shahdza/article/details/6314818 (内容比较老了)

 

下面总结一下树状数组的题型 :

1.最简单的单点更新区间查询 。 其实这个是树状数组的精髓了,不过入门的时候都会做些简单题找感觉吧。

下面附上简单题找感觉,动脑子的题后面贴。

 http://poj.org/problem?id=2299

http://poj.org/problem?id=2352 

http://poj.org/problem?id=1195 (二维的裸题呢)

http://poj.org/problem?id=2481 

http://poj.org/problem?id=2029 (又是一个二维的裸题)

 

 2.插线问点问题:

这是一个经典问题,题目描述为:给连续区间内同时给出某种操作。 然后询问单点的值是多少。

例如:把区间【a,b-1】内的数同时加上v,然后询问c点的值。 我们可以这么操作: 在更新a处的值(加上v) ,然后更新b 处的值(减去v)

这样任何落在区间【a,b-1】的点都会加上1不在区间上的点都不变。 

可以参考上图树状数组(总结篇) 

 下面附上一道练习:

http://poj.org/problem?id=2155

http://acm.hdu.edu.cn/showproblem.php?pid=3584  (三维问题)

http://acm.hdu.edu.cn/showproblem.php?pid=4267  (维护多颗树状数组问题)

http://acm.hdu.edu.cn/showproblem.php?pid=5057 (维护多颗树状数组问题)

 插线问点是离线树状数组的基础问题哦。。 

 

3:区间修改区间查询的问题 。

这个问题显得不是那么重要(用线段树组搞很简单的)。用树状数组搞就是在深入理解下他的用法。

我们可以维护两个树状数组。

具体可以搞出  http://poj.org/problem?id=3468

 我的代码:

/*
by cao ni ma
hehe
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <list>
#include <queue>
#include <stack>
using namespace std;
typedef long long LL;
const int MAX = 100000+10;
const int inf = 0x3f3f3f3f;
LL C[2][MAX];
int n,m;
int lowbit(int x) {return x&-x;}
void add(LL *C,int x,LL val) {
    for(int i=x;i<=n;i+=lowbit(i)) C[i]+=val;
}
LL sum(LL *C,int x) {
    LL res=0;
    for(int i=x;i;i-=lowbit(i)) res+=C[i];
    return res;
}
LL val[MAX]; char str[3];
int main()
{
    //freopen("in","r",stdin);
    
//freopen("out","w",stdout);
    LL a,b,c;
    while(scanf("%d %d",&n,&m)==2) {
        memset(C,0,sizeof(C));
        for(int i=1;i<=n;i++) {
            scanf("%I64d",&val[i]);
            add(C[0],i,val[i]);
        }
        for(int i=0;i<m;i++) {
            scanf("%s",str);
            if(str[0]=='Q') {
                scanf("%I64d %I64d",&a,&b);
                LL res=sum(C[1],b)*b-sum(C[1],a-1)*(a-1)+sum(C[0],b)-sum(C[0],a-1);
                printf("%I64d\n",res);
            }
            else {
                scanf("%I64d %I64d %I64d",&a,&b,&c);
                add(C[1],a,c);
                add(C[1],b+1,-c);
                add(C[0],a,-c*(a-1));
                add(C[0],b+1,b*c);
            }
        }
    }
    return 0;

}
View Code

相关文章:

  • 2022-12-23
  • 2021-09-01
  • 2021-09-08
  • 2021-07-28
  • 2021-11-10
  • 2021-08-04
  • 2021-09-15
  • 2022-12-23
猜你喜欢
  • 2022-02-23
  • 2021-06-27
  • 2021-11-18
相关资源
相似解决方案