芻議線段樹 2 (區間修改,區間查詢)

Qian·JXのjoker發表於2024-08-09

線段樹 \(2\)

接上一講

https://www.cnblogs.com/yingxilin/p/18350988
(沒看的同學們可以先看這篇)

上一講裡我們已經介紹了單點修改,區間查詢的線段樹了。
在這一講裡,我們開始學習支援區間修改,區間查詢的線段樹。
考慮之前的做法,之前的查詢區間會被分為 \(O(logn)\),從而求解,但因為所有子樹節點要一起更新, 複雜度淪為 \(O(n)\) ,無法接受。

tag-懶惰標記

這時,我們可以給要修改的點加一個懶惰標記 \(tag\) ,標記為“該點已經被修改,其子節點尚未被更新”,再將其下傳。之後在遞迴進入其父節點時再判斷其是否帶有 \(tag\) 標記,若有,再將其更新。如此一來,就不用修改一個點時更新所有子樹節點,只需要把要用到的節點更新,大大減小了演算法複雜度。具體操作看程式碼,有註釋。

區間更改,區間查詢

例題:
https://www.luogu.com.cn/problem/P3372

大意:區間加,區間求和

程式碼:

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define FOR(i,_l,_r) for(int i=_l;i<=_r;i++)
#define ls (p<<1)
#define rs (p<<1|1)
#define mid ((l+r)>>1)//這裡一定要記得打上括號,不然會調得很慘
#define len(x) (t[x].r-t[x].l+1)
const int N=1e5+5;
struct Node{
	int l,r;//左右兒子
	int sum,tag;//區間和,懶惰標記
}t[N<<2];
int a[N];
int n,m;
void up(int p){//向上更新
	t[p].sum=t[ls].sum+t[rs].sum;
}
void build(int p,int l,int r){//建樹
	t[p].l=l;t[p].r=r;
	if(l==r){
		t[p].sum=a[l];
		return;
	}
	build(ls,l,mid);
	build(rs,mid+1,r);
	up(p);
}

void down(int p){//懶惰標記下放
	if(!t[p].tag) return;//無tag,return;
	int k=t[p].tag;
	t[ls].sum+=k*len(ls);//更新左區間
	t[rs].sum+=k*len(rs);//更新右區間
	t[ls].tag+=k;//傳給左兒子
	t[rs].tag+=k;//傳給右兒子
	t[p].tag=0;//記得把當前標記清零
}

void change(int p,int L,int R,int v){//修改
	int l=t[p].l;
	int r=t[p].r;
	if(L<=l&&r<=R){
		t[p].sum+=v*len(p);//更新當前節點的區間和
		t[p].tag+=v;//更新tag
		return;
	}
	down(p);//下放
	if(L<=mid) change(ls,L,R,v);
	if(R>mid) change(rs,L,R,v);
	up(p);
}

int query(int p,int L,int R){//查詢
	int l=t[p].l;
	int r=t[p].r;
	if(L<=l&&r<=R)  return t[p].sum;
	down(p);//下放
	int ans=0;
	if(L<=mid) ans+=query(ls,L,R);
	if(R>mid) ans+=query(rs,L,R);
	return ans;
}

signed main(){
	freopen("test.in","r",stdin);
	freopen("test.out","w",stdout);
	// ios::sync_with_stdio(false);
	// cin.tie(NULL);
	cin>>n>>m;
	FOR(i,1,n)  cin>>a[i];
	build(1,1,n);//建樹
	while(m--){
		// cout<<1;
		int opt,x,y,k;
		cin>>opt>>x>>y;
		if(opt==1){
			cin>>k;
			change(1,x,y,k);
		}
		else  cout<<query(1,x,y)<<endl;
	}
	return 0;
}

留個作業

https://www.acwing.com/problem/content/description/263/

相關文章