zoukankan      html  css  js  c++  java
  • [模板]非递归线段树(zkw的变异版本)

    类似于zkw,但空间只用两倍,zkw要4倍。

    链接

    可以下传标记,打熟后很好码。

    #include <set>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <assert.h>
    #include <algorithm>
    
    using namespace std;
    
    #define LL long long
    #define debug(...) fprintf(stderr, __VA_ARGS__)
    #define GO debug("GO
    ")
    
    inline int rint() {
      register int x = 0, f = 1; register char c;
      while (!isdigit(c = getchar())) if (c == '-') f = -1;
      while (x = (x << 1) + (x << 3) + (c ^ 48), isdigit(c = getchar()));
      return x * f;
    }
    
    template<typename T> inline void chkmin(T &a, T b) { a > b ? a = b : 0; }
    template<typename T> inline void chkmax(T &a, T b) { a < b ? a = b : 0; }
    
    
    const int maxN = 1e5 + 10;
    
    int n, h, m;
    LL sum[maxN * 2], tag[maxN * 2];
    
    void build() {
      for (h = 1; 1 << h < n; ++ h);//计算树高
      for (int i = n + 1; i <= 2 * n; ++ i) sum[i] = rint();
      for (int i = n; i >= 1; -- i) sum[i] = sum[i<<1] + sum[i<<1|1];
    }
    
    void add(int x, int val, int len) {
      sum[x] += val * len;
      if (x <= n) tag[x] += val;//如果不是是叶子才打标记
    }
    
    void pu(int x) {
      int len = 1;
      while (x > 1) len<<=1, x >>= 1, sum[x] = sum[x<<1] + sum[x<<1|1] + tag[x] * len;//从下往上,儿子的值不一定正确,需要累上标记
    }
    
    void pd(int x) {
      for (int i = h, len = 1 << (h - 1); i > 0; -- i, len >>= 1) {//从上到下len初始为1<<(h-1)
        int y = x >> i;
        if (tag[y]) {//下传标记
          add(y<<1, tag[y], len);
          add(y<<1|1, tag[y], len);
          tag[y] = 0;
        }
      }
    }
    
    void modify(int l, int r, int val) {
      l += n, r += n;
      int l0 = l, r0 = r;
      for (int len = 1; l <= r; l = (l + 1) >> 1, r = (r - 1) >> 1, len <<= 1) {//从下往上,叶子节点len为1
        if (l & 1) add(l, val, len);
        if (r & 1 ^ 1) add(r, val, len);
      }
      pu(l0); pu(r0);//别忘了pushup
    }
    
    LL query(int l, int r) {
      l += n, r += n;
      pd(l); pd(r);//查询前要下传该区间标记
      LL ans = 0;
      for (; l <= r; l = (l + 1) >> 1, r = (r - 1) >> 1) {
        if (l & 1) ans += sum[l];
        if (r & 1 ^ 1) ans += sum[r];
      }
      return ans;
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
      freopen("xhc.in", "r", stdin);
      freopen("xhc.out", "w", stdout);
    #endif
      n = rint(), m = rint();
      build();
      int op, x, y, k;
      while (m --) {
        op = rint(), x = rint(), y = rint();
        if (op == 1) {
          k = rint();
          modify(x, y, k);
        } else {
          printf("%lld
    ", query(x, y));
        }
      }
    }
    
  • 相关阅读:
    python3----练习......
    python3----练习题(....)
    python3----requests
    python3----练习题(爬取电影天堂资源,大学排名,淘宝商品比价)
    python3----练习题(图片转字符画)
    python3----练习题(....)
    ConfigParser 读写配置文件
    数据驱动ddt+excel数据读取
    数据驱动ddt
    expected_conditions判断页面元素
  • 原文地址:https://www.cnblogs.com/cnyali-Tea/p/10587028.html
Copyright © 2011-2022 走看看