线段树之区间求和 POJ 3468 线段树入门
来源:互联网 发布:淘宝被骗怎么退款 编辑:程序博客网 时间:2024/06/05 17:59
题目就是要经常查询某短区间的和,而且要经常修改一段区间的值即同是把这个区间的每个元素都加上一数
这中要求线段树就可以实现修改和查询的时间都是logN的
下面是代码,注释可以参考一下,希望可以解释清楚,第一次学可能不好懂,但出几个简单的数据模拟一下就大概懂了
#include<algorithm>#include<cstdio>#include<iostream>using namespace std;#define maxn 100005struct point{ int left,right; long long sum;//初始化的时候sum是当前这个区间的所有元素的和 其实sum究竟表示什么很难说清楚我感觉 //非要说的话他就是 原始的left right闭区间元素的和再加上后来在把某段区间的元素都增加一定值的时候在执行update时二分出的区间递归到能够小于或等于这个区间时的增加的和 //是不很拗口????反正我觉得是的,这个不用图很难表述清楚 long long jia;//对当前整个区间每个元素应该增加的值}node[4*maxn];int score[maxn];//原始的数据void buildtree(int left,int right,int u)//初始化的建树函数{ node[u].left=left;//设置区间的左端点 node[u].right=right;//设置区间的右端点 node[u].jia=0;//初始化整个区间每个元素都要增加的值为零 if(left==right) node[u].sum=score[left];//如果区间的长度为一则区间和就为它所存的元素 else//反之则二分递归下去 { buildtree(left,(left+right)/2,2*u); buildtree(((left+right)/2)+1,right,2*u+1); node[u].sum=node[2*u].sum+node[2*u+1].sum;//当前区间的和为他左右的子区间的和 }};void updata(int l,int r,int val,int u)//更新区间,把区间l到r的元素都加上val{ node[u].sum+=(long long)(r-l+1)*(long long)val;//区间的和增加 int mid=(node[u].left+node[u].right)/2;//二分当前的区间 if(node[u].left==l&&node[u].right==r)//如果要跟新的区间与现在的区间是同一个区间就把每个元素要加的值加在jia上以便需要统计这段区间的和的时候用 node[u].jia+=(long long)val; else if(r<=mid)//二分递归, updata(l,r,val,2*u); else if(l>mid) updata(l,r,val,2*u+1); else { updata(l,mid,val,2*u); updata(mid+1,r,val,2*u+1); }}int n,m;char temp;long long query(int left,int right,int u)//查询区间left到right区间的所有元素的和//left 和 right为要查找的区段和的区间{ int mid=(node[u].left+node[u].right)/2;//二分当前区间的中值 long long t=(long long)(right-left+1)*(long long )node[u].jia;//t 也是一个不好描述的东西 //因为node[u].jia是 node[u].left 和node[u].right 内每个元素应该增加的值 所以要求 left到right这个包含在node[u].left 和node[u].right //内的区间的元素的和当然要加上t了即(right-left+1)*node[u].jia 要注意可能会溢出 if(node[u].left==left&&node[u].right==right)//如果要求和的区间恰好的等于当前节点的区间就返回这个难懂的node[u].sum return node[u].sum; if(right<=mid)//在左区间就去左区间去找 return query(left,right,2*u)+t; if(left>mid)//到右区间去找 return query(left,right,2*u+1)+t; return query(left,mid,2*u)+query(mid+1,right,2*u+1)+t;//否则就说明left到right区间横跨了左右2个子区间,就要把left到right的区间用mid分成2个部分}int main(){ //freopen("in.txt","r",stdin); while(scanf("%d%c%d%c",&n,&temp,&m,&temp)!=EOF) { for(int i=1;i<=n;i++) scanf("%d%c",&score[i],&temp); char c;int s,e,h; buildtree(1,n,1); for(int i=0;i<m;i++) { scanf("%c%c",&c,&temp); if(c=='C') { scanf("%d%c%d%c%d%c",&h,&temp,&s,&temp,&e,&temp); updata(h,s,e,1); } if(c=='Q') { scanf("%d%c%d%c",&s,&temp,&e,&temp); printf("%I64d\n",query(s,e,1)); } } } return 0;}
- 线段树之区间求和 POJ 3468 线段树入门
- poj 3468(线段树应用:区间求和)
- 【线段树】-POJ-3468-区间增减&区间求和
- POJ 3468 线段树 区间增减 区间求和
- POJ 3468 线段树 区间更新+区间求和
- 线段树区间求和
- poj 3468 线段树对一个区间加减和求和
- poj 3468 (线段树区间更新及求和)
- poj 3468 线段树(成段增减 区间求和)
- POJ 3468 线段树区间更新求和模板
- poj3468(线段树区间求和)
- poj3468 线段树区间求和
- 线段树区间更新+求和
- POJ 3468 线段树插线问线区间求和
- poj 3468 线段树成段增减+区间求和
- POJ 3468 线段树区间
- Poj 3468 A Simple Problem with Integers (线段树 区间更新 区间求和)
- POJ 3468 A Simple Problem with Integers(线段树功能:区间加减区间求和)
- CentOS6.3在安装nfs服务时无法找到portmap的解决办法
- 调用linux_shell、另一个可执行程序调用exec函数
- hibernate 中createSQLQuery 聚合分组 java.lang.NumberFormatException: For input string:错误的一个解决办法
- delphi中的Assigned
- MFC如何使控件大小随着对话框大小自动调整
- 线段树之区间求和 POJ 3468 线段树入门
- 多线程程序debug linux
- APUE读书笔记-第8章进程控制
- Linux NFS服务器的安装与配置
- 程序员的自我修养
- brk和sbrk及内存分配函数相关
- 06-一个IP绑定多个域名(根据端口号不同进行绑定)
- 动态链接库dll,静态链接库lib, 导入库lib
- php学习笔记