普通线段树维护区间最大最小值(板子)
/* 线段树维护区间最大/小值就是按照原来给出的数据的顺序建造一颗二叉树,然后每一个节点维护 这个节点的子节点且包含这个节点的值中的最大/小值 */ #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 */