传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1754 线段树模板题
本题题意:
有多组测试数据, 给定长度为n的小组, 并且给定m个查询条件, 查询条件有 给定 c a b 1.如果c 为Q 表示 查找在a, b区间内最大的人数,
2.如果c为 U 更新区间 a小组的值为b
本题思路:
一道线段树模板题目,
#include<bits/stdc++.h>
using namespace std;
const int maxsize = 200005;
struct Node {
int l, r, sum;
}tree[maxsize * 4];
int stu[maxsize];
void push_up(int x) {
//tree[x].sum = tree[x<<1].sum + tree[x<<1|1].sum;
tree[x].sum = max(tree[x<<1].sum, tree[x<<1|1].sum); // 此处是求最大值
}
void build(int x, int l, int r) { //建立树
tree[x].l = l, tree[x].r = r;
if(l == r) {
tree[x].sum = stu[l];
} else {
int mid = (l + r) / 2;
build(x<<1, l, mid);
build(x<<1|1, mid + 1, r);
push_up(x);
}
}
void update(int x, int index, int data) { //更新树
int L = tree[x].l, R = tree[x].r;
if(L == R) { // 更新
tree[x].sum = data;
} else { // 更新
int mid = (L + R) / 2;
if(index <= mid) update(x<<1, index, data);
else update(x<<1|1, index, data);
push_up(x);
}
}
int query(int x, int l, int r) { //查找树
int L = tree[x].l, R = tree[x].r;
if(L >= l && r >= R) {
return tree[x].sum;
}else {
int mid = (L + R) / 2, res = 0;
if(mid >= l) res = query(x<<1, l, r);
if(mid < r) res = max(res, query(x<<1|1, l, r));
return res;
}
}
int main() {
int n, m, ans = 0;
while(~scanf("%d%d", &n, &m)) {
for(int i = 1; i <= n; i++) {
scanf("%d", &stu[i]);
}
build(1, 1, n);
char c;
int a, b;
getchar();
while(m--) {
scanf("%c%d%d", &c, &a, &b);
getchar();
if(c == 'Q') {
ans = query(1, a, b);
printf("%d\n", ans);
} else if(c == 'U') {
update(1, a, b);
}
}
}
return 0;
}
修改到: 此题目不是区间求解线段树,最好不加lazy标记 比较快捷, 加lazy标记的版本:
#include<bits/stdc++.h>
using namespace std;
const int maxsize = 200005;
int stu[maxsize];
struct Node{
int l, r, lazy, max; // lazy是懒惰标记
void update(int num) {
max = num;
lazy = max;
}
}tree[maxsize * 4];
void pushup(int x) {
tree[x].max = max(tree[x<<1].max, tree[x<<1|1].max);
}
void pushdown(int x) {
int sum = tree[x].lazy / 2;
if(tree[x].lazy != 0) {
tree[x<<1].max = tree[x].max; // 此题是修改到并不是增加,减少
tree[x<<1].lazy = sum;
tree[x<<1|1].max = tree[x].max;
tree[x<<1|1].lazy = sum;
tree[x].lazy = 0;
}
}
void built(int x, int l, int r) {
tree[x].l = l; tree[x].r = r;
tree[x].max = tree[x].lazy = 0; // 初始化max, lazy防止push_down时未初始化出现错误
if(l == r) {
tree[x].max = stu[l];
} else {
int mid = (l + r) / 2;
built(x<<1, l, mid);
built(x<<1|1, mid + 1, r);
pushup(x);
}
}
void update(int x, int index, int data) {
int L = tree[x].l, R = tree[x].r;
int mid = (L + R) / 2;
if(L >= index && R <= index) {
tree[x].update(data);
} else {
//pushdown(x); //如果只是修改为或者修改到 那么就不用下方值了
// 下方的值后结果不变,如果是增加值,减少值,就需要下放了
if(index <= mid) update(x<<1, index, data);
else update(x<<1|1, index, data);
pushup(x);
}
}
int query(int x, int l, int r) {
int L = tree[x].l, R = tree[x].r;
int mid = (L + R) / 2;
if(l <= L && R <= r) {
return tree[x].max;
} else {
pushdown(x); // 此处需要下放 毕竟query只是查找,不会修改以后的值了
int res = 0;
if(l <= mid) res = query(x<<1, l, r);
if(mid < r) res = max(res, query(x<<1|1, l, r));
return res;
}
}
int main() {
int n, m, ans = 0;
while(~scanf("%d%d", &n, &m)) {
for(int i = 1; i <= n; i++) {
scanf("%d", &stu[i]);
}
built(1, 1, n);
char c;
int a, b;
getchar();
while(m--) {
scanf("%c%d%d", &c, &a, &b);
getchar();
if(c == 'Q') {
ans = query(1, a, b);
printf("%d\n", ans);
} else if(c == 'U') {
update(1, a, b);
}
}
}
return 0;
}