欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

skkyk:线段树浅谈

程序员文章站 2022-10-08 18:26:48
推荐前辈学姐博客文章,写的很细 https://www.cnblogs.com/TheRoadToTheGold/p/6254255.html 学学半,此随笔主要是加深自己对线段树的理解 题目:洛谷P3374模(mu)板题 (话说为什么是树状数组,主要是因为我太菜了不会懒标记) 等改天问一下学长们懒 ......

推荐前辈学姐博客文章,写的很细

https://www.cnblogs.com/theroadtothegold/p/6254255.html

学学半,此随笔主要是加深自己对线段树的理解

题目:洛谷p3374模(mu)板题

(话说为什么是树状数组,主要是因为我太菜了不会懒标记)

//代码中的位运算其实就是乘除2的一些操作
#include<cstdio> using namespace std; int n,m,ans; struct node { int left,right,num; }tree[500000*4+5];//经典的四倍空间,我也不知道为什么 int input[500000+5]; void build(int index,int l,int r)//建树,一棵满二叉树 { tree[index].left=l,tree[index].right=r; if(l==r) { tree[index].num=input[l]; return ; } int mid=(l+r)>>1; build(index<<1,l,mid);build(index<<1|1,mid+1,r); tree[index].num=tree[index<<1].num+tree[index<<1|1].num; } void add(int index,int target,int k)//单点修改,变量是序号、目标、修改值 { tree[index].num+=k;//对于每个可以递归到的点都是包含目标target这个点的集合,都要一并加上k if(tree[index].left==tree[index].right)//单点集合返回 return ; if(target<=tree[index<<1].right) add(index<<1,target,k); if(target>=tree[index<<1|1].left) add(index<<1|1,target,k);//两个if语句都是判断是否存在交集,是则进行下一层 } void query(int index,int l,int r)//区间求和(区间查询) { if(tree[index].right<=r&&tree[index].left>=l) { ans+=tree[index].num;//对于区间的子集累计答案 return ;//避免累计区间子集的区间子集 ??exm } if(tree[index].right==tree[index].left) return ; if(tree[index<<1].right>=l) query(index<<1,l,r); if(tree[index<<1|1].left<=r) query(index<<1|1,l,r);//同为寻找交集 return ; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",input+i); build(1,1,n);//建树 for(int i=1,a,x,y;i<=m;i++) { scanf("%d%d%d",&a,&x,&y); if(a==1) add(1,x,y);//单点修改 if(a==2) { ans=0; query(1,x,y);//区间查询 printf("%d\n",ans); } }
  return 0; }

等改天问一下学长们懒标记的具体