普通線段樹維護區間最大最小值(板子)
阿新 • • 發佈:2020-09-10
/* 線段樹維護區間最大/小值就是按照原來給出的資料的順序建造一顆二叉樹,然後每一個節點維護 這個節點的子節點且包含這個節點的值中的最大/小值 */ #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 */