1. 程式人生 > >線段樹模板(區間更新,區間求和,區間最值)

線段樹模板(區間更新,區間求和,區間最值)

線段樹模板

#include <iostream>
#include <stdio.h>
#define ll long long
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define il inline
using namespace std;
const ll MAXN = 1e5 + 10;
struct Tree {
	ll sum;
	ll lazy;
	ll maxn;
	ll minn;
} t[MAXN<<2];
il void
push_up(ll rt) { //向上更新 t[rt].sum = t[rt << 1].sum + t[rt << 1 | 1].sum; t[rt].maxn = max(t[rt << 1].maxn ,t[rt << 1 | 1].maxn); t[rt].minn = min(t[rt << 1].minn ,t[rt << 1 | 1].minn); } il void push_down(ll rt, ll m) { if(t[rt].lazy) { //若有標記,則將標記向下移動一層 t[rt <<
1].lazy += t[rt].lazy; t[rt << 1 | 1].lazy += t[rt].lazy; t[rt << 1].sum += (m - (m >> 1)) * t[rt].lazy; t[rt << 1 | 1].sum += (m >> 1) * t[rt].lazy; t[rt << 1].minn += t[rt].lazy; t[rt << 1 | 1].minn+= t[rt].lazy; t[rt << 1].maxn += t[rt]
.lazy; t[rt << 1 | 1].maxn+= t[rt].lazy; t[rt].lazy = 0;//取消本層標記 } } il void build(ll l,ll r, ll rt) { //建樹 t[rt].lazy = 0; if(l == r) { scanf("%lld",&t[rt].sum); t[rt].minn=t[rt].sum; t[rt].maxn=t[rt].sum; return; } ll mid = (l + r) >> 1; build(lson); build(rson); push_up(rt);//向上更新 } il void update(ll L,ll R, ll key, ll l,ll r, ll rt) { //區間更新 if(L <= l && R >= r) { t[rt].sum+=(r - l + 1) * key; t[rt].minn+=key; t[rt].maxn+=key; t[rt].lazy+=key; return; } push_down(rt, r - l + 1);//向下更新 long long int mid = (l + r) >> 1; if(L <= mid) update(L, R, key, lson); if(R > mid) update(L, R, key, rson); push_up(rt);//向上更新 } il ll query(ll L, ll R, ll l, ll r,ll rt) { //區間求和 if(L <= l && R >= r) return t[rt].sum; push_down(rt, r - l + 1);//向下更新 ll mid = (l + r) >> 1; ll ans = 0; if(L <= mid) ans += query(L, R, lson); if(R > mid) ans += query(L, R, rson); return ans; } il ll query_min(ll L, ll R, ll l, ll r,ll rt) { //區間求最小值 if(L <= l && R >= r) return t[rt].minn; push_down(rt, r - l + 1);//向下更新 ll mid = (l + r) >> 1; ll ans = 0x3f3f3f3f; if(L <= mid) ans = min(ans,query(L, R, lson)); if(R > mid) ans =min(ans,query(L, R, rson)) ; return ans; } il ll query_max(ll L, ll R, ll l, ll r,ll rt) { //區間求最大值 if(L <= l && R >= r) return t[rt].maxn; push_down(rt, r - l + 1);//向下更新 ll mid = (l + r) >> 1; ll ans = 0; if(L <= mid) ans = max(ans,query(L, R, lson)); if(R > mid) ans = max(ans,query(L, R, rson)); return ans; } int main() { ll n,l,r,v; char a; int t; cin>>t; for(ll i=1; i<=t; i++) { scanf("%lld", &n); build(1, n, 1); while(cin>>a&&a!='e') { if(a=='a') { scanf("%lld%lld%lld",&l,&r,&v); update(l,r,v,1,n,1); } else if(a=='s') { scanf("%lld%lld",&l,&r); printf("%lld\n",query(l,r,1,n,1)); } else if(a=='m') { scanf("%lld%lld",&l,&r); printf("%lld\n",query_min(l,r,1,n,1)); } else { scanf("%lld%lld",&l,&r); printf("%lld\n",query_max(l,r,1,n,1)); } } } return 0; }