23th 【树状数组】树状数组1&&2
来源:互联网 发布:进出口企业的数据 编辑:程序博客网 时间:2024/05/19 03:23
数状数组两种基本的用法
树状数组其实就是巧妙的利用了二分,有效记录一些段的值。
这图是网上找的,相当的好。
这些长条就是树桩数组记录的和值。
举个例子,想找数组1-11的和,只需要先加数状数组的11,在加10,最后加8。
可以看出来这就是一个每次分一半的数。
实现起来很简单但是有一些部分很巧妙,比如说lowbit,可以快速找到数的父节点或子节点。
不懂可以上网搜一下树状数组,图看懂了基本上就懂了。
首先是单点修改,区间求和。
【题目描述】:
如题,已知有N个元素组成的数列(下标从1开始计数),你需要进行下面两种操作:
1.将某一个数加上x
2.求出某区间每一个数的和
【输入描述】:
第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。
第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。
接下来M行每行包含3个整数,表示一个操作,具体如下:
操作1: 格式:1 x k 含义:将第x个数加上k
操作2: 格式:2 x y 含义:输出区间[x,y]内每个数的和
【输出描述】:
输出包含若干行整数,即为所有操作2的结果。(输出不超过int类型)
【样例输入】:
5 51 5 4 2 31 1 32 2 51 3 -11 4 22 1 4
【样例输出】:
1416
【时间限制、数据范围及描述】:
时间:1s 空间:128M
对于30%的数据:N<=8,M<=10
对于70%的数据:N<=10000,M<=10000
对于100%的数据:N<=100000,M<=100000
#include<iostream>#include<stdio.h>#include<algorithm>using namespace std;const int Maxn=100010;int a[Maxn],t[Maxn];int n,m,x,y,way,k;inline int getint(){ int x=0;char c=getchar();int f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar(); return x*f;}int lowbit(int x){
return x&(-x);
}void update(int x,int val){for(int i=x;i<=n;i+=lowbit(i))t[i]+=val;}//修改int sum(int x){ int ans=0; for(int i=x;i>=1;i-=lowbit(i)) ans+=t[i]; return ans;}//求和int main(){//freopen("bintreeone.in","r",stdin);//freopen("bintreeone.out","w",stdout); n=getint();m=getint(); for(int i=1;i<=n;i++) {a[i]=getint(); update(i,a[i]);} for(int i=1;i<=m;i++) { way=getint(); if(way==1){ x=getint(); y=getint(); update(x,y);} if(way==2){ x=getint(); y=getint(); printf("%d\n",sum(y)-sum(x-1)); } }return 0;}
树状数组没有图讲不清楚,但是写起来相当简单,只要记住两个函数和一个lowbit就行了。
其次就是区间修改,单点查询。
为什么只能反过来呢,其实这里我们用差分数组保存,这样区间修改是两个点的修改,而单点查询即为差分数组复原也就是求和。
这样就能利用树状数组的结构了。
【题目描述】:
如题,已知一个数列(下标从1开始计数),你需要进行下面两种操作:
1.将某区间每一个数,加上x
2.获取某一个数的值
【输入描述】:
第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。
第二行包含N个用空格分隔的整数,第i个数字表示数列第i项的初始值。
接下来M行每行包含2或4个整数,表示一个操作,具体如下:
操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k
操作2: 格式:2 x 含义:输出第x个数的值
【输出描述】:
输出包含若干行整数,即为所有操作2的结果。
【样例输入】:
5 51 5 4 2 31 2 4 22 31 1 5 -11 3 5 72 4
【样例输出】:
610
【时间限制、数据范围及描述】:
时间:1s 空间:128M
对于30%的数据:N<=8,M<=10
对于70%的数据:N<=10000,M<=10000
对于100%的数据:N<=100000,M<=100000
#include<iostream>#include<stdio.h>#include<algorithm>using namespace std;const int Maxn=100010;int a[Maxn],t[Maxn];int n,m,x,y,way,k;inline int getint(){ int x=0;char c=getchar();int f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar(); return x*f;}int lowbit(int x){return x&(-x);}void update(int x,int val){for(int i=x;i<=n;i+=lowbit(i))t[i]+=val;}int sum(int x){ int ans=0; for(int i=x;i>=1;i-=lowbit(i)) ans+=t[i]; return ans;}int main(){//freopen("bintreetwo.in","r",stdin);//freopen("bintreetwo.out","w",stdout); n=getint();m=getint(); for(int i=1;i<=n;i++) { a[i]=getint(); update(i,a[i]-a[i-1]);} for(int i=1;i<=m;i++) { way=getint(); if(way==1){ x=getint(); y=getint(); k=getint(); update(x,k);update(y+1,-k);} if(way==2){ x=getint(); printf("%d\n",sum(x)); } }return 0;}
阅读全文
0 0
- 23th 【树状数组】树状数组1&&2
- hust1433-树状数组-2
- hdu4000-树状数组-2
- 树状数组(2)
- 树状数组(2)
- 树状数组(2)
- 树状数组(2)
- 【模板】树状数组 2
- 树状数组模板2
- 【模板】树状数组2
- 树状数组(1)
- 树状数组(1)
- 【模板】树状数组 1
- P3374 树状数组 1
- 树状数组(1)
- 【模板】树状数组1
- 树状数组
- 树状数组
- HDU 5793 A Boring Question (快速幂 + 乘法逆元 + 费马小定理)
- UVA 1599 理想路径
- VS2010中“Stack around the variable 'XXX' was corrupted.”处理方法
- 单例设计模式
- java并发编程实战-取消与关闭2
- 23th 【树状数组】树状数组1&&2
- linux内核深入学习参考
- 草根学Python(八) 模块与包
- sublime安装方式及快捷键
- myeclipse的svn插件解决冲突的几种情况。
- 操作系统复习-4.2文件系统实现
- C++ 变量初始化顺序
- Fidder--实现手机的抓包
- MFC编程--windows编程的概念