线段树合集 | 基础篇

先理解线段树 放一个大佬的博客

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

区间求和+ 区间更新

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值