树状数组和线段树
2011-12-07 23:29
204 查看
树状数组和线段数组,两者在复杂度上同级, 但是树状数组的常数明显优于线段树, 其编程复杂度也远小于线段树.
树状数组的作用被线段树完全涵盖, 凡是可以使用树状数组解决的问题, 使用线段树一定可以解决, 但是线段树能够解决的问题树状数组未必能够解决.
树状数组的突出特点是其编程的极端简洁性, 使用lowbit技术可以在很短的几步操作中完成树状数组的核心操作,与之相关的便是其代码效率远高于线段树。
另外,当问题推广到高维情形时高维树状数组有高维线段树所无法企及的常数优势。
HDU 1166 敌兵布阵
树状数组:
树状数组的作用被线段树完全涵盖, 凡是可以使用树状数组解决的问题, 使用线段树一定可以解决, 但是线段树能够解决的问题树状数组未必能够解决.
树状数组的突出特点是其编程的极端简洁性, 使用lowbit技术可以在很短的几步操作中完成树状数组的核心操作,与之相关的便是其代码效率远高于线段树。
另外,当问题推广到高维情形时高维树状数组有高维线段树所无法企及的常数优势。
HDU 1166 敌兵布阵
树状数组:
#include <iostream> using namespace std; #define maxn 1000010 int c[maxn], n; int a[maxn]; char ch[100]; int lowbit(int x) { return x & (-x);//结果等价与return x & (x^(x-1)); } void Add(int x, int add) { while(x <= n) { c[x] += add; x += lowbit(x); } } int sum(int x) { int s = 0; while(x > 0) { s += c[x]; x -= lowbit(x); } return s; } int main() { int t, as, bs, i, q = 1; scanf("%d", &t); while(t--) { scanf("%d", &n); memset(c, 0, sizeof(c)); for(i = 1; i <= n ;i++) { scanf("%d", &a[i]); Add(i, a[i]); } printf("Case %d:\n", q++); while(scanf("%s" , ch) != EOF) { if(!strcmp(ch, "End")) break; else if(!strcmp(ch, "Query")) { scanf("%d%d", &as, &bs); printf("%d\n", sum(bs) - sum(as - 1)); }else if(!strcmp(ch, "Add")) { scanf("%d%d", &as, &bs); Add(as, bs); } else if(!strcmp(ch, "Sub")) { scanf("%d%d", &as, &bs); Add(as, -bs); } } } }
线段树
#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int MAXN=50003; int v[MAXN],sum; typedef struct { int left,right,mid; int count; }line; line l[4*MAXN]; void Creat(int a,int b,int r) { if(a==b) { l[r].left=l[r].right=a; l[r].count=v[a]; return; } l[r].left=a; l[r].right=b; l[r].mid=(a+b)/2; Creat(a,l[r].mid,2*r); Creat(l[r].mid+1,b,2*r+1); l[r].count=l[2*r].count+l[2*r+1].count; } void Add(int n,int m,int r) { if(l[r].left==n&&l[r].right==n) { l[r].count+=m; return; } if(n>l[r].mid) { Add(n,m,2*r+1); } else { Add(n,m,2*r); } l[r].count=l[2*r].count+l[2*r+1].count; } void Query(int a,int b,int r) { if(l[r].left==a&&l[r].right==b) { sum+=l[r].count; } else if(a>l[r].mid) { Query(a,b,2*r+1); } else if(b<=l[r].mid) { Query(a,b,2*r); } else { Query(a,l[r].mid,2*r); Query(l[r].mid+1,b,2*r+1); } } int main() { int cnt=1; int t; scanf("%d",&t); while(t--) { printf("Case %d:\n",cnt++); int n; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&v[i]); } Creat(1,n,1); char s[7]; while(scanf("%s",s),s[0]!='E') { int b,c; scanf("%d %d",&b,&c); if(s[0]=='Q') { sum=0; Query(b,c,1); printf("%d\n",sum); } else if(s[0]=='A') { Add(b,c,1); } else if(s[0]=='S') { Add(b,-1*c,1); } } } return 0; }
相关文章推荐
- POJ 2352 Stars(树状数组 or 线段树)
- Hdu1166 敌兵布阵 [分块][树状数组][线段树]
- poj2155二维线段树,二维树状数组
- HDU 5877 2016大连网络赛 Weak Pair(树状数组,线段树,动态开点,启发式合并,可持久化线段树)
- HDOJ1556 Color the ball 【线段树】+【树状数组】+【标记法】
- BZOJ - 4034 树上操作 (Dfs序列 + 线段树) || (树链剖分 + 线段树)|| (树状数组)
- hdoj Stars 1541 (树状数组模板&&线段树)
- POJ3468--A Simple Problem with Integers--线段树/树状数组 改段求段
- HDU 1166 敌兵布阵 【简单的树状数组||线段树】
- 有一种树叫做线段树,有一种数组叫做树状数组
- hdu4893 Wow! Such Sequence!,树状数组,线段树,单点修改,区间更新
- POJ3321 线段树,树状数组 建树经典题
- 【区间查询_树状数组、线段树、次方数组】最大矩形
- 区间操作(线段树、树状数组、懒人标记、RMQ算法)
- 线段树(树状数组)hdu4267
- 【HDU5927 2016CCPC东北地区大学生程序设计竞赛 - 重现赛 F】【dfs序 + 线段树 or 树状数组 复杂度计算】Auxiliary Set 一个点如果是好点或是两个好点的LCA就是好
- 树状数组和线段树
- POJ 2155 Matrix (二维线段树入门,成段更新,单点查询 / 二维树状数组,区间更新,单点查询)
- 【可持久化线段树】【树状数组】[ZOJ 2112]Dynamic Rankings
- 线段树和树状数组问题补充