先理解线段树 放一个大佬的博客
https://blog.csdn.net/whereisherofrom/article/details/78969718
有题目+题解的大佬博客
https://www.cnblogs.com/ya-cpp/p/4165777.html
较简单的题目:
HDU 1754 I Hate it
单点更新 + 区间最值
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 1e6 + 5;
int arr[maxn], tree[maxn];
void build(int node, int start, int emd)
{
if (start == emd) {
tree[node] = arr[start];
} else {
int mid = (start + emd) / 2;
int left_node = 2 * node + 1;
int right_node = 2 * node + 2;
build(left_node, start, mid);
build(right_node, mid + 1, emd);
tree[node] = max(tree[left_node], tree[right_node]);
}
}
void update(int node, int start, int emd, int idx, int val)
{
if (start == emd) {
arr[idx] = val;
tree[node] = val;
} else {
int mid = (start + emd) / 2;
int left_node = 2 * node + 1;
int right_node = 2 * node + 2;
if (idx >= start && idx <= mid) {
update(left_node, start, mid, idx, val);
} else {
update(right_node, mid + 1, emd, idx, val);
}
tree[node] = max(tree[left_node], tree[right_node]);
}
}
int query(int node, int start, int emd, int L, int R)
{
int maxx = 0;
if (L <= start && R >= emd) {
return tree[node];
} else {
int mid = (start + emd) / 2;
if (L <= mid) {
maxx = max(maxx, query(node * 2 + 1, start, mid, L, R));
}
if (R >mid ) {
maxx= max(maxx, query(node * 2 + 2, mid + 1, emd, L, R));
}
return maxx;
}
}
int main()
{
int n, m;
while (~scanf("%d%d", &n, &m)) {
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
getchar();
build(0, 0, n - 1); // 建树
char a ;
int b, c;
for (int i = 0; i < m; i++) {
scanf("%c%d%d", &a, &b, &c);
getchar();
if (a == 'Q') {
int mm = 0;
mm = query(0, 0, n - 1, b - 1, c - 1);
printf("%d\n", mm);
} else if (a == 'U') {
update(0, 0, n - 1, b - 1, c);
}
}
}
return 0;
}
ZOJ 2706 Thermal Death of the Universe
区间求和+ 区间更新
PS:这不是我的代码 我用的板子没有用懒标记 可能是因为这个一直TLE
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <queue>
#include <vector>
#define maxn 32500
#define maxe 11000
#define INF 0x3f3f3f
#define lson l,mid,u<<1
#define rson mid+1,r,u<<1|1
#define ll_int long long int
using namespace std;
ll_int seg[maxn<<2];
ll_int pau[maxn<<2];
//bool flag[maxn<<2];
ll_int initsum;
void PushUp(int u){
seg[u] = seg[u<<1] + seg[u<<1|1];
}
void PushDown(int l,int r,int u){
if(pau[u]){
int mid = (l + r)/2;
pau[u<<1] = pau[u<<1|1] = pau[u];
seg[u<<1] = (ll_int)(mid - l + 1) * pau[u];
seg[u<<1|1] = (ll_int)(r - mid) * pau[u];
pau[u] = 0;
}
}
void build(int l,int r,int u){
seg[u] = 0;
pau[u] = 0;
if(l == r){
scanf("%lld",&seg[u]);
initsum += seg[u];
return;
}
int mid = (l + r)/2;
build(lson);
build(rson);
PushUp(u);
}
void Update(int L,int R,int num,int l,int r,int u){
if(L <= l && r <= R){
pau[u] = num;
seg[u] = (ll_int)(r - l + 1)* num;
return;
}
PushDown(l,r,u);
int mid = (l + r)/2;
if(L <= mid) Update(L,R,num,lson);
if(R > mid) Update(L,R,num,rson);
PushUp(u);
}
ll_int Query(int L,int R,int l,int r,int u){
if(L <= l && r <= R){
return seg[u];
}
PushDown(l,r,u);
int mid = (l + r)/2;
ll_int ret = 0;
if(L <= mid) ret += Query(L,R,lson);
if(R > mid) ret += Query(L,R,rson);
return ret;
}
void print(int l,int r,int u){
if(l == r){
if(l == 1) printf("%lld",seg[u]);
else printf(" %lld",seg[u]);
return;
}
PushDown(l,r,u);
int mid = (l + r)/2;
print(lson);
print(rson);
}
int main(){
// freopen("input.txt","r",stdin);
int n,m;
while(scanf("%d%d",&n,&m) == 2){
initsum = 0;
build(1,n,1);
for(int i=1;i<=m;i++){
int a,b;
scanf("%d%d",&a,&b);
ll_int sum = Query(a,b,1,n,1);
int ave = sum/(b-a+1);
if(sum > 0 && seg[1] <= initsum){ //为正的UP;
if(sum % (b-a+1)) ave++;
}
else if(sum < 0 && seg[1] > initsum){ //为负的down;
if(sum % (b-a+1)) ave--;
}
Update(a,b,ave,1,n,1);
}
print(1,n,1);
printf("\n\n");
}
}
POJ 3468 A Simple Problem with Integers
区间求和+ 区间更新