HDU1754 I Hate It(树状数组 or 线段树)
题目链接。
分析:
本题可以用树状数组,也可以用线段树。
树状数组:
对于树状数组,请详见本随笔。
要注意的是,比如说上图,要求 2 到 4 之间的最大值, c[4] 并非 2 到 4 之间的最大值,因为 c[4] 是 1 到 4 之间的最大值。这时候就只能单独看A[4], A[3], A[2]了。
AC代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; const int maxn = 200000 + 10; int num[maxn], c[maxn], n, m; int lowbit(int t){ return t & (-t); } void add(int x, int d){ num[x] = d; while(x <= n){ if(c[x] < d){ c[x] = d; } else break; x = x + lowbit(x); } } int get_max(int l, int r){ int ans = num[r]; while(l != r){ r--;//这里也注意下 while(r - lowbit(r) > l){ //这里注意下 ans = max(ans, c[r]); r -= lowbit(r); } ans = max(ans, num[r]); } return ans; } int main(){ int a, b; char ch[2]; while(scanf("%d%d", &n, &m) == 2){ memset(num, 0, sizeof(num)); memset(c, 0, sizeof(c)); for(int i=1; i<=n; i++){ scanf("%d", &a); add(i, a); } for(int i=0; i<m; i++){ scanf("%s%d%d", ch, &a, &b); if(ch[0] == 'Q'){ printf("%d\n", get_max(a, b)); } else{ add(a, b); } } } return 0; }
线段树:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <cstdio> #include <cmath> #include <iostream> #include <queue> #include <cstring> using namespace std; const int maxn = 200000+10; struct Node { int left; int right; int max; }node[maxn*4]; int a[maxn]; void build(int l, int r, int i) { node[i].left = l; node[i].right = r; if(l == r) { node[i].max = a[l]; return ; } int mid = (l+r)/2; build(l, mid, i*2); build(mid+1, r, i*2+1); node[i].max = max(node[i*2].max, node[i*2+1].max); } void Update(int id, int value, int i) { if(node[i].left == node[i].right) { node[i].max = value; return ; } int mid = (node[i].left + node[i].right)/2; if(id <= mid) Update(id, value, i*2); //要用 <= else Update(id, value, 2*i+1); node[i].max = max(node[i*2].max, node[i*2+1].max); } int Query(int l, int r, int i) { if(node[i].left == l && node[i].right == r) return node[i].max; else { int mid = (node[i].left + node[i].right)/2; int ans = -1; if(l <= node[i].left && node[i].right <= r) return node[i].max; if(l <= mid) ans = max(ans, Query(l, r, i*2)); if(mid < r) ans = max(ans, Query(l, r, i*2+1)); return ans; //else里的这一小部分也可以这样写 /* if(mid >= r) return Query(l, r, 2*i); else if(mid < l) return Query(l, r, 2*i+1); else { int ans = -1; ans = max(ans, Query(l, mid, 2*i)); ans = max(ans, Query(mid+1, r, 2*i+1)); return ans; }*/ } } int main(){ int n, m; while(scanf("%d%d", &n, &m) == 2) { for(int i=1; i<=n; i++) scanf("%d", &a[i]); build(1, n, 1); char s[2]; int x, y; for(int i=0; i<m; i++) { scanf("%s %d%d", s, &x, &y); if(s[0] == 'Q') printf("%d\n", Query(x, y , 1)); else Update(x, y, 1); } } return 0; }