》》点击进入原题测试《《

思路:好像是第一次这么印象深刻的写线段树,说实话,这个题确实很有意思,值得学习。

看了大神讲解视频,但是自己写的还是超时了。

参考来自 https://blog.csdn.net/yiqzq/article/details/81211652 个人认为可以作为模板

#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
#include <stack>
#include <set>
#include <cctype>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define MOD 1e9+7
#define PI acos(-1)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e5 + 5;

int n, q;
int MIN[maxn << 2];//记录区间最小值
int lazy[maxn << 2];//延迟标记减法
int ans[maxn << 2];//记录答案数量
int b[maxn << 2];//记录b数组

//线段树基本操作,pushup和pushdown
void pushup(int rt) {
    MIN[rt] = min(MIN[rt << 1], MIN[rt << 1 | 1]);
    ans[rt] = ans[rt << 1] + ans[rt << 1 | 1];
}

void pushdown(int rt) {
    if(lazy[rt]) {
        lazy[rt << 1] += lazy[rt];
        lazy[rt << 1 | 1] += lazy[rt];
        MIN[rt << 1] -= lazy[rt];
        MIN[rt << 1 | 1] -= lazy[rt];
        lazy[rt] = 0;
    }
}
//建树
void build(int l, int r, int rt) {
    lazy[rt] = 0;
    ans[rt] = 0;
    if(l == r) {
        scanf("%d", &b[rt]);
        MIN[rt] = b[rt];
        return ;
    }
    int m = (l + r) >> 1;
    build(lson);
    build(rson);
    pushup(rt);
}
//区间更新,需要注意当NIN减为0的时候,要ans++并且重新将b的值赋给MIN
void updata(int L, int R, int l, int r, int rt) {
    if(L <= l && R >= r) {
        MIN[rt]--;
        if(MIN[rt]) {
            lazy[rt]++;
            return;
        } else {
            if(l == r) {
                ans[rt]++;
                MIN[rt] = b[rt];
                return;
                /*血的教训,这个return不能放大括号外面,因为如果递归到某个节点MIN是0
                但是又不是叶子节点,那么还是需要继续递归直到找到叶子节点为止
                */
            }

        }
    }
    pushdown(rt);
    int m = (l + r) >> 1;
    if(L <= m) updata(L, R, lson);
    if(R > m) updata(L, R, rson);
    pushup(rt);
}
//查询
int query(int L, int R, int l, int r, int rt) {
    if(L <= l && R >= r) {
        return ans[rt];
    }
    pushdown(rt);
    int m = (l + r) >> 1;
    int sum = 0;
    if(m >= L) sum += query(L, R, lson);
    if(m < R) sum += query(L, R, rson);
    return sum;
}
int main() {
    while(~scanf("%d%d", &n, &q)) {
        build(1, n, 1);
        for(int i = 1; i <= q; i++) {
            char op[10];
            int a, b;
            scanf("%s%d%d", op, &a, &b);
            if(op[0] == 'q') {
                printf("%d\n", query(a, b, 1, n, 1));
            } else {
                updata(a, b, 1, n, 1);
            }
        }
    }
    return 0;
}
复制来的代码

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-02-11
  • 2022-12-23
  • 2021-05-30
  • 2021-06-20
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2021-09-28
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-09-02
相关资源
相似解决方案