区间修改,区间查询(线段树)
创始人
2024-02-10 19:46:06
0

线段树

线段树-Segment Tree是一种基于分治思想的二叉树数据结构,用于区间信息修改和查询

区间修改和查询

延迟标记

延迟是设计算法和解决问题的重要思路之一,可以减少徒劳的操作,有效降低时间复杂度。
试想我们在线段树上修改区间[l,r]中的每一个元素的值,而且该区间覆盖了节点node代表的区间[node.l, node.r], 我们当然可以逐一更新子树node中的所有元素,但这个逐一更新的操作是不必要的,因为后续的询问指令可能没有用到[l,r]的子区间。即时更新完全是浪费cpu。
修改时,在节点区间被待修改目标区间完全覆盖时立即返回,回溯时向当前节点累计一个延迟标记,标记其子节点尚未更新。
所有暂时没有被修改的节点都推迟到将来必须被修改时再执行修改(后续查询或修改操作递归进入这些节点时)。
延迟标记是线段树中自上而下传递数据的方式。

例题
A Simple Problem with Integers

给定一个长度为 N 的数列 P,以及 W条指令,每条指令可能是以下两种之一:
C l r d,表示把数列中第 l~r个数都加 d。
Q l r,表示询问数列中第 l∼r个数的和。
对于每个询问,输出一个整数表示答案。
输入格式
第一行两个整数 N,W。
第二行 N个整数 P[i]。
接下来 W行表示 W条指令,每条指令的格式如题所示。
输出格式
对于每个询问,输出一个整数表示答案。
每个答案占一行。
数据范围
1≤N,W≤105, |d|≤10000, |P[i]|≤109
输入样例:
11 4
1 2 3 4 5 6 7 8 9 10 11
Q 5 6
Q 2 9
C 2 9 2
Q 4 10
输出样例:
11
44
61

线段树解决方案

每个节点用结构体模拟
节点包含四个分量: 区间和sum , add增量(兼作延迟标记),左右端点
broadcast函数实现了延迟标记的向下广播
本题属于区间修改,区间查询

代码实现
#include 
#include 
#include 
#include 
using namespace std;typedef long long LL;
//simple integer  
//segment tree with postpone markconst int N = 100007;int n, w;
int P[N];struct STree
{int l,r;LL sum , add;
}ST[4 * N];void pushup(int u)
{ST[u].sum = ST[u << 1].sum + ST[u << 1 | 1].sum;}void broadcast(int k)
{STree & root = ST[k], & left = ST[k << 1];STree & right = ST[k << 1 | 1];if(root.add)//postpone mark is valid{left.add += root.add, left.sum += (LL)(left.r - left.l + 1) * root.add;right.add += root.add, right.sum +=(LL)(right.r - right.l + 1) * root.add;root.add = 0;}
}
void build(int k , int l , int r)
{if(l == r){ST[k] = {l,r,P[l]};return;	} ST[k] = {l,r};int mid = (l + r)>> 1;build(k << 1, l, mid);build(k << 1 | 1, mid + 1, r);pushup(k);
}
//change
void modify(int k , int l , int r, int d)
{if(ST[k].l >= l && ST[k].r <= r){//whole region need to be modifiedST[k].sum +=(LL)(ST[k].r - ST[k].l + 1) * d;ST[k].add += d;//MARK}else{broadcast(k);int mid = ST[k].l + ST[k].r >> 1;if(l <= mid) modify(k << 1, l, r, d);if(r > mid) modify(k << 1 | 1, l, r, d);pushup(k);}}
LL ask(int k , int l , int r)
{if(ST[k].l >= l && ST[k].r <= r) return ST[k].sum;broadcast(k);//only spread one layer every time as needint mid = ST[k].l + ST[k].r >> 1;LL val = 0;//return answerif(l <= mid) val += ask(k << 1, l, r);if( r > mid) val += ask(k << 1|1, l, r);return val;
}
int main()
{
//	freopen("TEST.in","r",stdin);
//	freopen("TEST.out","w",stdout);scanf("%d%d",&n, &w);for(int i = 1; i <= n; i ++)scanf("%d",&P[i]);// read inbuild(1, 1, n);//build Segment treeint l, r, d;char op[2];while(w --){scanf("%s%d%d",op, &l,&r);if(67 == op[0]){scanf("%d",&d);modify(1,l,r,d);}else printf("%lld\n",ask(1,l,r));}//	fclose(stdin);
//	fclose(stdout);return 0;
}

相关内容

热门资讯

世事繁华不及你惊鸿一瞥什么意思... 世事繁华不及你惊鸿一瞥什么意思?理解这句话首先要明白惊鸿一瞥的意思。那惊鸿一瞥什么意思呢——只是匆匆...
朋友梦见我在火里让她救我是什么... 朋友梦见我在火里让她救我是什么意思?如果你们是单纯的朋友可能说明友谊很好吧,如果不是单纯的,那可能是...
猜谜啦!猜谜啦!很多谜语哦! 猜谜啦!猜谜啦!很多谜语哦!1,开方2,3.4,5,圆周率6。王,8,丕9,10,丰11,晶12,偶...
女孩子说感觉有点怪 女孩子说感觉有点怪这对她来说比较突然,而且也许她现在自己也不能分辨出她对你的感觉到底是喜欢还是好朋友...
南京银行股份有限公司关于实施“... 证券简称: 南京银行 证券代码: 601009 编号: 2025-052优先股简称:南银优1 优先股...
科技赋能“气象+”,一场助企富... (来源:工人日报) “8月头季稻卖一块八毛,10月份再收一季,两季加起来一亩地收上千元!”四川...
取一杯天上水是指月光吗 取一杯天上水是指月光吗不是。是指下雨的时候接一杯天上掉下来的雨水,最纯洁的水最有灵性的水。这杯水在晚...
为什么越来越觉得赚钱比男朋友重... 为什么越来越觉得赚钱比男朋友重要?我也这么认为,因为男朋友不够好。还没遇到真心待自己的人或者,是因为...
腐团儿现实中有男朋友吗? 腐团儿现实中有男朋友吗?腐团儿现实中有男朋友吗?这个谁知道呢一或者暗中有也不一定这种明星私事我也不是...
元宵与汤圆有啥区别 元宵与汤圆有啥区别元宵和汤圆的区别:1.馅料选择不同,汤圆馅偏软,咸甜荤素选择众多,元宵馅偏硬,以甜...