1. 程式人生 > 實用技巧 >普通線段樹維護區間最大最小值(板子)

普通線段樹維護區間最大最小值(板子)

/*
線段樹維護區間最大/小值就是按照原來給出的資料的順序建造一顆二叉樹,然後每一個節點維護
這個節點的子節點且包含這個節點的值中的最大/小值
*/
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
const int MAX_LEN =1000 ;
int seg_tree[MAX_LEN << 2];
int Lazy[MAX_LEN << 2];
int arr[MAX_LEN]; //從下往上更新 節點 void push_up (int root) { seg_tree[root] = max(seg_tree[root << 1], seg_tree[root << 1 | 1]); //最小值改min } //從上向下更新,左右孩子 void push_down (int root, int L, int R) { if(Lazy[root]){ Lazy[root << 1] += Lazy [root]; Lazy[root << 1
| 1] += Lazy[root]; int mid = (L + R) >> 1; seg_tree[root << 1] += Lazy[root] * (mid - L + 1); seg_tree[root << 1 | 1] += Lazy[root] * (R - mid); Lazy[root] = 0; } } //建樹 //[L,R]就是對應arr數組裡面的數 void build (int root, int L, int R) { Lazy[root] = 0;
if(L == R) { seg_tree[root] = arr[L]; return ; } int mid = (L + R) >> 1; build(root << 1, L, mid); build(root << 1 | 1, mid + 1, R); push_up(root); } //區間查詢 //查詢區間[LL,RR]的最大/小值 int query (int root, int L, int R, int LL, int RR) { if (LL <= L && R <= RR) return seg_tree[root]; push_down(root, L, R); //每次訪問都去檢查Lazy 標記 int Ans = 0; int mid = (L + R) >> 1; if(LL <= mid) Ans = max(Ans, query(root << 1, L, mid, LL, RR)); //最小值改min if(RR > mid) Ans = max(Ans, query(root << 1 | 1, mid + 1, R, LL, RR)); //最小值改min return Ans; } //區間修改 +-某值 //使得區間[LL,RR]的值都加上val void update_Interval(int root, int L, int R, int LL, int RR, int val){ if (LL <= L && R <= RR) { Lazy[root] += val; seg_tree[root] += val * (R - L + 1); return ; } push_down(root, L, R); int mid = (L + R) >> 1; if (LL <= mid) update_Interval(root << 1, L, mid, LL, RR, val); if (RR > mid) update_Interval(root << 1 | 1, mid + 1, R, LL , RR, val); push_up(root); } //單點修改 可以改為某值,或者+-某值 //把pos位置的值改成val void update(int root, int L, int R, int pos, int val) { if(L == R){ seg_tree[root] = val; //點直接變為某值 return ; } int mid = (L + R) >> 1; if(pos <= mid) update(root << 1, L, mid, pos, val); else update(root << 1 | 1, mid + 1, R, pos, val); push_up(root); } int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) { scanf("%d",&arr[i]); } build(1,1,n); while(m--) { int l,r; scanf("%d%d",&l,&r); printf("%d\n",query(1,1,n,1,r)); } return 0; } /* 5 4 3 2 4 5 1 1 2 2 4 3 5 2 3 */