NYOJ 116 树状数组
来源:互联网 发布:腾讯云怎么绑定域名 编辑:程序博客网 时间:2024/04/28 12:35
初学树状数组。。
这是线段树的图,由图可知,c[1]=a[1];c2=a[1]+a[2];c[3]=a[3];c[4]=a[1]+a[2]+a[3]+a[4];c[5]=a[5];
c[6]=a[5]+a[6];c[7]=a[7];c[8]=a[1]+a[2]+a[3]+a[4]+a[5]+a[6]+a[7]+a[8];
可以得到这个规律,i为奇数时,c[i]=a[i],这里1,3,5,7便是例子。偶数时这里就跟2的幂有关系了,i的因子中最多有2的多少次幂,例如4,2的2次幂,为4,所以从a[4]数共4个数的值,即a[1],a[2],a[3],a[4],当i=6时,因子数最大为2,所以数2个数,即a[5],a[6],同理i=8时,2的三次幂,等于8,即a[1]+.....a[8]的值.网上查询可知,公式为
c[n]=a(n-a^k+1)+......+a[n]; (其中k为从右往走数0的个数,也即第一个出现1的位置,起点从0开始)
这里可以用一个函数计算得
int lowbit(int x)
{
return x&(-x);
}
这个函数怎样理解呢?
x=1时,x的二进制表示为(假设位数为8) 0000 0001
-x的二进制表示为 1111 1111
---> 0000 0001 =1;
x=6时 x的二进制表示为 0000 0110
-x的二进制表示为 1111 1010
---> 0000 0010 =2;
这里相信你明白了,若不懂负数的二进制表示,可百度查之
这个函数的目的就是求出2^k (k为往右数第一个出现1的位置起点从0开始或者0出现的个数,见上)
接下来就是求和了,
int Sum(int n)
{
int sum=0;
while(n>0)
{
sum+=c[n];
n=n-lowbit(n);
}
return sum;
}
这里具体该怎样理解呢?我们可以看成求一段路径的和,不同于普通的一维数组按照下标为1一次递增或递减,这里是按照树的结构,每次logn,即求路径(x,x-lowit(x),....1)为下标的和
最后修改某个结点的值
void change(int i,int x)
{
while(i<=m) //m个结点的总和
{
c[i]=c[i]+x;
i=i+lowbit(i);
}
}
如果上面求和理解了,这步应该很快理解了,改变了某个结点的值,那么对应的路径上相应的点也要改变,结束的条件即为到达根结点。
下面来看看这道题
链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=116
1,若采取常规的方法,求解,时间的复杂度为O(n^2);
2,采取树状数组的方法,AC代码:
#include<iostream>#include<stdio.h>#include<cstring>using namespace std;int c[1000008],m,Q,t;int lowbit(int x){ return x&(-x);}int Sum(int n){ int sum=0; while(n>0) { sum=sum+c[n]; n=n-lowbit(n); } return sum;}void change(int i,int x){ while(i<=m) { c[i]=c[i]+x; i=i+lowbit(i); }} int main(){ scanf("%d%d",&m,&Q); char key[10]; int start,end; for(int i=1;i<=m;++i) { scanf("%d",&t); change(i,t); } while(Q--) { scanf("%s%d%d",key,&start,&end); if(key[0]=='Q') printf("%d\n",Sum(end)-Sum(start-1)); else if(key[0]=='A') change(start,end); } return 0;}
参考资料来源:http://www.cnblogs.com/zhangshu/archive/2011/08/16/2141396.html
http://hi.baidu.com/czyuan_acm/item/b14bff6ab6ffd093c5d249db
- NYOJ 116 树状数组
- 【树状数组】nyoj 116 123 士兵杀敌
- nyoj 树状数组系列
- NYOJ 2689(树状数组)
- NYOJ-522 Interval【树状数组】
- nyoj 123 树状数组 插线问点
- nyoj 322 Sort 【树状数组】
- nyoj 522 树状数组入门
- NYOJ 233 &&NYOJ 322 Sort(树状数组)
- NYOJ 116:士兵杀敌 第一次用树状数组AC题目
- nyoj 116 士兵杀敌(二) 树状数组
- NYOJ 116-士兵杀敌2 树状数组:插点求线
- NYOJ-116 士兵杀敌(二)树状数组
- nyoj 116 士兵杀敌(二)(树状数组)
- nyoj 树状数组 522Interval 116士兵杀敌(二)
- NYOJ 116 士兵杀敌(二) 树状数组 & 线段树
- nyoj--116--士兵杀敌(二)(树状数组)
- nyoj--116 士兵杀敌(二)(树状数组)
- c#常见面试题及答案
- 从头到脚编译安装VPS上所有东西
- 第一个QT程序
- android应用开发笔记---_Handler的使用
- 手把手学习企业型网站之四中间部分的完成
- NYOJ 116 树状数组
- Android Touch相关资料收集
- 数据结构-线性表
- DM9000网卡中文手册
- 计算球体积
- Computer Vision中一些常用的图像数据库
- oracle学习路线!
- 一个简单的tcp client/server小程序
- Duplicate entry 't_id' for key 'PRIMARY' 错误