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

线段树

线段树-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;
}

相关内容

热门资讯

正扬科技创业板IPO获受理 拟... 汽车电子零部件企业正扬科技闯关IPO。5月7日深交所网站显示,广东正扬传感科技股份有限公司(简称“正...
刘海星会见孟加拉国外长卡利勒 5月7日,中共中央对外联络部部长刘海星在北京会见孟加拉国外长卡利勒。刘海星祝贺孟新政府施政实现良好开...
挪威央行加息以应对通胀压力 挪威央行7日宣布,将基准利率上调0.25个百分点至4.25%,以应对持续高企的通胀压力。挪威央行表示...
U17女足亚洲杯中国队6比0胜... 北京时间5月7日晚,2026亚足联U17女足亚洲杯小组赛A组的争夺全部结束。在苏州太湖足球运动中心1...
菲海岸警卫队1架岛人型机蓄意抵... 中国海警局新闻发言人姜略表示,5月6日,中方向阳红33号船位中国鲎藤礁附近海域开展正常生态环境调查。...