线段树 成段更新
来源:互联网 发布:js 字符串转对象 编辑:程序博客网 时间:2024/05/21 15:39
线段树就是许多线段组成的,并对每条线段进行操作,线段树的节点满足二叉树,所以某个节点的左右儿子是 2*rt,和2*rt+1;
举例说明:已知线段[2,5] [4,6] [0,7];求点2,4,7分别出现了多少次
在[0,7]区间上建立一棵满二叉树:(为了和已知线段区别,用【】表示线段树中的线段)
【0,7】
/ \
【0,3】 【4,7】
/ \ / \
【0,1】 【2,3】 【4,5】 【6,7】
/ \ / \ / \ / \
【0,0】 【1,1】 【2,2】 【3,3】 【4,4】 【5,5】 【6,6】 【7,7】
三条已知线段插入过程:
[2,5]
--[2,5]与【0,7】比较,分成两部分:[2,3]插到左儿子【0,3】,[4,5]插到右儿子【4,7】
--[2,3]与【0,3】比较,插到右儿子【2,3】;[4,5]和【4,7】比较,插到左儿子【4,5】
--[2,3]与【2,3】匹配,【2,3】记录+1;[4,5]与【4,5】匹配,【4,5】记录+1
[4,6]
--[4,6]与【0,7】比较,插到右儿子【4,7】
--[4,6]与【4,7】比较,分成两部分,[4,5]插到左儿子【4,5】;[6,6]插到右儿子【6,7】
--[4,5]与【4,5】匹配,【4,5】记录+1;[6,6]与【6,7】比较,插到左儿子【6,6】
--[6,6]与【6,6】匹配,【6,6】记录+1
[0,7]
--[0,7]与【0,7】匹配,【0,7】记录+1
插入过程结束,线段树上的记录如下(红色数字为每条线段的记录n):
【0,7】
1
/ \
【0,3】 【4,7】
0 0
/ \ / \
【0,1】 【2,3】 【4,5】 【6,7】
0 1 2 0
/ \ / \ / \ / \
【0,0】 【1,1】 【2,2】 【3,3】 【4,4】 【5,5】 【6,6】 【7,7】
0 0 0 0 0 0 1 0
询问操作和插入操作类似,也是递归过程,略
2——依次把【0,7】 【0,3】 【2,3】 【2,2】的记录n加起来,结果为2
4——依次把【0,7】 【4,7】 【4,5】 【4,4】的记录n加起来,结果为3
7——依次把【0,7】 【4,7】 【6,7】 【7,7】的记录n加起来,结果为1
练习:http://acm.nyist.net/JudgeOnline/code.php?runid=260199 士兵杀敌三。#include<stdio.h>#include<string.h>#define maxn 4000002int sum=0;struct tree{ int left,right,n; int mid() { return (left+right)>>1; }};tree a[maxn];void buildtree(int s,int t,int n){ a[n].left=s; a[n].right=t; int mid=a[n].mid(); if(s==t) return ; buildtree(s,mid,2*n); buildtree(mid+1,t,2*n+1);}void insert(int s,int t,int step,int h)//插入:{ if(s==a[step].left&&t==a[step].right) { a[step].n+=h; return ; } if(a[step].left==a[step].right) return ;//当前线段没有儿子,插入结束; int mid=a[step].mid(); if(mid>=t) insert(s,t,step*2,h);//如果中点在T的右边,插到左儿子 else if(mid<s) insert(s,t,step*2+1,h);//在S的左边,插到右儿子。 else//否则,中点在ST中间,各分到左右儿子里。 { insert(s,mid,step*2,h); insert(mid+1,t,step*2+1,h); }}void count(int s,int t,int step)//访问{ if(a[step].n!=0) sum+=a[step].n; if(a[step].left==a[step].right) return; int mid=a[step].mid(); if(mid>=t) count(s,t,step*2); else if(mid<s) count(s,t,step*2+1); else { count(s,mid,step*2); count(mid+1,t,step*2+1); }}int main(){ int m,b,c,i,t,h; char ss[6]; while(~scanf("%d%d",&c,&m)) { for(i=0;i<=m;i++) a[i].n=0; buildtree(1,m,1); while(c--) { scanf(" %s",ss); if(strcmp(ss,"ADD")==0) { scanf("%d%d%d",&b,&t,&h); insert(b,t,1,h); } if(strcmp(ss,"QUERY")==0) { sum=0; scanf("%d",&t); count(t,t,1); printf("%d\n",sum); } } } return 0;}
- 线段树 成段更新
- 线段树 成段更新
- 线段树 成段更新
- 线段树 成段更新 hdu1698
- hdu 1698 线段树 成段更新
- poj 3468 线段树 成段更新
- hdu 4325 线段树 成段更新
- hdu 4107 线段树 成段更新
- 线段树HDU1698(成段更新)
- HDU 4027 ( 线段树 -- 成段更新)
- UVA11992----线段树的成段更新
- hdu 3577 线段树,成段更新
- hdu 1698 线段树-成段更新
- poj 3468 线段树--成段更新
- 线段树 (成段更新)
- poj 2528 线段树--成段更新
- hdu 4902 线段树-成段更新
- poj 3468线段树 成段更新
- 函数指针赋值
- Oracle学习笔记安装篇之在Redhat Enterprise Linux 6.3 x86_64下安装Oracle11g R2
- 收藏的关于算法博客链接
- TI DSP C6000 功能单元和执行操作
- 工作
- 线段树 成段更新
- linux下tar压缩使用
- 一片牧草,草每天生长的速度相同,这片牧草可供27头牛吃6天,可供46只羊吃9天,如果一头牛的吃草量等于2只羊的吃草量,那么11头牛和20只羊一起吃可以吃多少天?
- MSSQL笔记七
- DX9、XP游戏和更多3D绘图 - OpenGL - 还有未来吗?
- 57 wpf 椭圆圈圈
- 笔记:js内置对象及自定义对象
- FPGA_TPMS_10_12
- 硬件加速的选择OpenGL、DirectX