zoukankan      html  css  js  c++  java
  • HZNUACM寒假集训Day5小结 线段树 树状数组

    线段树

      什么时候用线段树   

      1.统计量可合并

      2.修改量可合并

      3.通过统计量可直接修改统计量

      一句话:满足区间加法即可使用线段树维护信息

      理解Lazy Tage 

      蓝色是要把信息及时维护的节点,红色是本次区间修改操作Lazy Tage下传停止的位置。

      

      模板  Just a Hook  HDU-1698

      

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<queue>
    using namespace std;
    
    const int maxn = 100050 * 4;  //线段树范围开4倍
    
    struct Tree {
        int l, r, sum, maxx;
    };
    
    Tree node[maxn];
    int a[maxn];
    int lazy[maxn];
    
    void Pushdown(int rt, int m) {
        if (lazy[rt]) {
            lazy[rt << 1] = lazy[rt];
            lazy[rt << 1 | 1] = lazy[rt];
            node[rt << 1].sum = lazy[rt] * (m - (m >> 1));
            node[rt << 1 | 1].sum = lazy[rt] * (m >> 1);
            lazy[rt] = 0;
        }
    }
    
    void Pushup(int i) {
        node[i].sum = node[i << 1].sum + node[i << 1 | 1].sum;
        node[i].maxx = max(node[i << 1].maxx, node[i << 1 | 1].maxx);
    }
    
    void Build(int i, int l, int r) {
        lazy[i] = 0;
        node[i].l = l;
        node[i].r = r;
        if (l == r) {
            node[i].maxx = a[l];
            node[i].sum = a[l];
            return;
        }
        int mid = l + r >> 1;
        Build(i << 1, l, mid);
        Build(i << 1 | 1, mid + 1, r);
        Pushup(i);
    }
    
    int getsum(int i, int l, int r) {
        if (node[i].l == l && node[i].r == r) return node[i].sum;
        int mid = node[i].l + node[i].r >> 1;
        Pushdown(i, node[i].r - node[i].l + 1);
        if (r <= mid) return getsum(i << 1, l, r);
        else if (l > mid) return getsum(i << 1 | 1, l, r);
        else return getsum(i << 1, l, mid) + getsum(i << 1 | 1, mid + 1, r);
    }
    
    void update(int i, int l, int r,int v) {
        if (node[i].r == r && node[i].l == l) {
            lazy[i] = v;
            node[i].sum = v * (r - l + 1);
            return;
        }
        if(node[i].l == node[i].r) return;
        int mid = node[i].l + node[i].r >> 1;
        Pushdown(i, node[i].r - node[i].l + 1);
        if (r <= mid) update(i << 1, l, r, v);
        else if (l > mid) update(i << 1 | 1, l, r, v);
        else {
            update(i << 1, l, mid, v);
            update(i << 1 | 1, mid + 1, r, v);
        }
        Pushup(i);
    }
    
    int main() {
        int kase = 1;
        int m, n, x, y, z, q;
        string op;
        int T;
        scanf("%d", &T);
        while (T--) {
            scanf("%d%d", &n, &q);
            for (int i = 1; i <= n; i++) a[i] = 1;
            Build(1, 1, n);
            while (q--) {
                scanf("%d%d%d", &x, &y, &z);
                update(1, x, y, z);
            }
            printf("Case %d:The total value of the hook is %d.\n", kase, getsum(1, 1, n));
            kase++;
        }
        return 0;
    }

       “树状数组支持的操作:1、区间和、区间异或和、区间乘积和RMQRMQ(显然,支持的操作都具有交换律,这也算是树状数组的一大特性吧)2、单点修改 ”

       

          code

       

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<algorithm>
    #include<queue>
    #include<set>
    #include<map>
    #include<cmath>
    const double PI = acos(-1.0);
    #define INF 0x3f3f3f3f
    typedef long long ll;
    using namespace std;
    
    int n, m, tree[2000010];
    
    inline int lowbit(int k) {   //lowbit(x)是x的二进制表达式中最低位的1所对应的值
        return k & -k;
    }
    
    void add(int x, int k) {
        while (x <= n) {
            tree[x] += k;
            x += lowbit(x);
        }
    }
    
    int sum(int x) {
        int ans = 0;
        while (x) {
            ans += tree[x];
            x -= lowbit(x);
        }
        return ans;
    }
    
    
    int main() {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++) {
            int a;
            scanf("%d", &a);
            add(i, a);
        }
        for (int i = 1; i <= m; i++) {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            if (a == 1) add(b, c);
            if (a == 2) printf("%d", sum(c) - sum(b - 1));
        }
        return 0;
    }
  • 相关阅读:
    [Python] 糗事百科文本数据的抓取
    [Python] 文件扫描
    [Python] 根据博客园用户名抓取其所有文章的标题及其链接
    ParagraphString
    IrregularGridCollectionView处理不定宽度的标签cell
    Java多线程与并发
    设计模式之代理模式
    javascript设置百分比保留两位小数。
    Java基础知识总结(异常机制、集合、JUC、IO)
    Java底层知识JVM、GC
  • 原文地址:https://www.cnblogs.com/hznumqf/p/12255523.html
Copyright © 2011-2022 走看看