摸清一、二维树状数组与线段树
2010-02-10 22:35
267 查看
先一维:
通过修改点,统计区间.
输入Q 5
输入C 2 6
5在这个区间里了。所以输出1.
再输入Q 3
输入C 2 6
输入当然是2.
通过修改区间,统计点。
翻纸牌差不多。
There is an array of n cards. Each card is putted face down on table. You have two queries: 1. T i j (turn cards from index i to index j, include i-th and j-th card - card which was face down will be face up; card which was face up will be face down) 2. Q i (answer 0 if i-th card is face down else answer 1)
This has solution for each query (and 1 and 2) has time complexity O(log n).
In array f (of length n + 1) we will store each query T (i , j) - we set f[i]++ and f[j + 1]--.
For each card k between i and j (include i and j) sum f[1] + f[2] + ... + f[k] will be increased for 1, for all others will be same as before (look at the image for clarification).
So our solution will be described sum (which is same as cumulative frequency) module 2.
![](https://oscdn.geek-share.com/Uploads/Images/Content/202007/20/0c01e9c2841330b88fdafe06421e89d9.jpg)
参考代码:
上面是两个树状数组一维的例子,一个是修改点,一个是修改区间。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202007/20/416fdbf98f2caff9a112e4d68603317a.jpg)
二维的树状数组运用:poj 2155 matrix
翻牌的二维使用:
代码:
怎么理解二维树状的含义,而为什么又要
updata(p2.x,p2.y);
updata(p1.x-1,p2.y);
updata(p2.x,p1.y-1);
updata(p1.x-1,p1.y-1);
![](https://oscdn.geek-share.com/Uploads/Images/Content/202007/20/f2af7418dd0cb6359b4cfff7130d79e7.jpg)
--------------
二、一维线段树
分析:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202007/20/d1d0f47eedaaf0cb51082f666dd71d5b.jpg)
通过修改点,统计区间.
输入Q 5
输入C 2 6
5在这个区间里了。所以输出1.
再输入Q 3
输入C 2 6
输入当然是2.
#include<stdio.h> #include<stdlib.h> #include<string.h> #define size 1001 typedef struct { int x,y; }node; int tree[size]; int n; inline int lowbit(int x) {return x&(-x);} void updata(int x) { while(x>0) { //printf("%d %d/n",p22.x,p22.y); tree[x]++; x-=lowbit(x); } } int read(int x) { int re=0; while(x<=n) { re+=tree[x]; x+=lowbit(x); } return re; } int main() { int x,t,a,b,tt; node p1,p2; char c[2]; scanf("%d",&x); while(x--) { scanf("%d%d",&n,&t); memset(tree,0,sizeof(tree)); while(t--) { scanf("%s",c); if(c[0]=='C') { scanf("%d%d",&p1.x,&p1.y); printf("%d",read(p1.x)-read(p1.y+1)); } else { scanf("%d",&a); updata(a); } }if(x)printf("/n"); } return 0; }
通过修改区间,统计点。
翻纸牌差不多。
There is an array of n cards. Each card is putted face down on table. You have two queries: 1. T i j (turn cards from index i to index j, include i-th and j-th card - card which was face down will be face up; card which was face up will be face down) 2. Q i (answer 0 if i-th card is face down else answer 1)
This has solution for each query (and 1 and 2) has time complexity O(log n).
In array f (of length n + 1) we will store each query T (i , j) - we set f[i]++ and f[j + 1]--.
For each card k between i and j (include i and j) sum f[1] + f[2] + ... + f[k] will be increased for 1, for all others will be same as before (look at the image for clarification).
So our solution will be described sum (which is same as cumulative frequency) module 2.
![](https://oscdn.geek-share.com/Uploads/Images/Content/202007/20/0c01e9c2841330b88fdafe06421e89d9.jpg)
参考代码:
#include<stdio.h> #include<stdlib.h> #include<string.h> #define size 1001 typedef struct { int x,y; }node; int tree[size]; int n; inline int lowbit(int x) {return x&(-x);} void updata(int x) { while(x>0) { //printf("%d %d/n",p22.x,p22.y); tree[x]++; x-=lowbit(x); } } int read(int x) { int re=0; while(x<=n) { re+=tree[x]; x+=lowbit(x); } return re; } int main() { int x,t,a,b,tt; node p1,p2; char c[2]; scanf("%d",&x); while(x--) { scanf("%d%d",&n,&t); memset(tree,0,sizeof(tree)); while(t--) { scanf("%s",c); if(c[0]=='C') { scanf("%d%d",&p1.x,&p1.y); updata(p1.x-1); updata(p1.y); } else { scanf("%d",&a); tt = read(a); if(!(tt%2)) { printf("0/n"); } else printf("1/n"); } }if(x)printf("/n"); } return 0; }
上面是两个树状数组一维的例子,一个是修改点,一个是修改区间。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202007/20/416fdbf98f2caff9a112e4d68603317a.jpg)
二维的树状数组运用:poj 2155 matrix
翻牌的二维使用:
代码:
#include<stdio.h> #include<stdlib.h> #include<string.h> #define size 1001 typedef struct { int x,y; }node; int tree[size][size]; int n; inline int lowbit(int x) {return x&(-x);} void updata(int x,int y) { int ty = y; while(x>0) { y=ty; while(y>0) { //printf("%d %d/n",p22.x,p22.y); tree[x][y]++; y-=lowbit(y); } x-=lowbit(x); } } int read(int x,int y) { int re=0,tm=y; while(x<=n) { y=tm; while(y<=n) { re+=tree[x][y]; y+=lowbit(y); } x+=lowbit(x); } return re; } int main() { int x,t,a,b,tt; node p1,p2; char c[2]; scanf("%d",&x); while(x--) { scanf("%d%d",&n,&t); memset(tree,0,sizeof(tree)); while(t--) { scanf("%s",c); if(c[0]=='C') { scanf("%d%d%d%d",&p1.x,&p1.y,&p2.x,&p2.y); updata(p2.x,p2.y); updata(p1.x-1,p2.y); updata(p2.x,p1.y-1); updata(p1.x-1,p1.y-1); } else { scanf("%d%d",&a,&b); tt = read(a,b); if(!(tt%2)) { printf("0/n"); } else printf("1/n"); } }if(x)printf("/n"); } return 0; }
怎么理解二维树状的含义,而为什么又要
updata(p2.x,p2.y);
updata(p1.x-1,p2.y);
updata(p2.x,p1.y-1);
updata(p1.x-1,p1.y-1);
![](https://oscdn.geek-share.com/Uploads/Images/Content/202007/20/f2af7418dd0cb6359b4cfff7130d79e7.jpg)
--------------
二、一维线段树
分析:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202007/20/d1d0f47eedaaf0cb51082f666dd71d5b.jpg)
struct seg{int l,r,len;};
//基本的线段树的构建 框架 void build(int p,int l,int r) { tree[p].l=l; tree[p].r=r; tree[p].len=r-l+1; if(l==r) return ; int m = (l+r)>>1; build(p*2,l,m); build(p*2+1,m+1,r); }
//查询 int query(int p,int l,int r,int n) { //tree[p].len--; int m =(l+r)>>1; if(l==r) return l; else if(tree[p*2].len>=n) { return query(p*2,l,m,n); } else {return query(p*2+1,m+1,r,n-tree[p*2].len);} }
//更新 void updata(int p,int l,int r,int x) { if(l==r&&l==x) { tree[p].len=0; return ; } int m =(l+r)>>1; if(m>=x){updata(p*2,l,m,x);} else { updata(p*2+1,m+1,r,x); } tree[p].len--; }
相关文章推荐
- 【区间DP】【二维线段树】【二维树状数组】2017.5.20 T3 deliver 题解
- POJ-2155-Matrix(二维树状数组 & 二维线段树)
- 单调栈、单调队列、线段树、LCA、二维树状数组、Bitset讲解
- poj 2155 二维线段树或树状数组入门
- poj2155二维线段树,二维树状数组
- poj1195 Mobile phones 二维线段树和二维树状数组两种做法 树套树
- BZOJ 4785 [Zjoi2017]树状数组 | 二维线段树
- [BZOJ4785][ZJOI2017]树状数组-二维线段树-概率与期望
- BZOJ4785 [Zjoi2017]树状数组 【二维线段树 + 标记永久化】
- POJ 1195 二维线段树||二维树状数组
- poj2155 二维树状数组 二位线段树 灵活运用 待补完
- 浅谈二维中的树状数组与线段树
- hdu1556 color the ball 树状数组区间更新单点查询(附线段树做法)与二维扩展
- POJ 2155 Matrix (二维线段树入门,成段更新,单点查询 / 二维树状数组,区间更新,单点查询)
- 单调栈、单调队列、线段树、LCA、二维树状数组、Bitset讲解
- POJ - 2155 Matrix (二维树状数组 + 区间修改 + 单点求值 或者 二维线段树 + 区间更新 + 单点求值)
- POJ 2155——Matrix(树套树,二维树状数组,二维线段树)
- 【BZOJ4785】[Zjoi2017]树状数组 树套树(二维线段树)
- tyvj P1716 - 上帝造题的七分钟 二维树状数组区间查询及修改 二维线段树
- poj 2155 二维树状数组 二维线段树