zoukankan      html  css  js  c++  java
  • 模板

    区间修改线段树:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define lt ls, l, m
    #define rt rs, m + 1, r
    #define ls (o<<1)
    #define rs (o<<1|1)
    
    const int MAXM = 100000 + 5;
    ll a[MAXM];
    ll st[MAXM * 4], lazy[MAXM * 4];
    
    inline void PushUp(int o) {
        st[o] = st[ls] + st[rs];
    }
    
    inline void PushDown(int o, int l, int r) {
        if(lazy[o]) {
            lazy[ls] += lazy[o];
            lazy[rs] += lazy[o];
            int m = l + r >> 1;
            st[ls] += lazy[o] * (m - l + 1);
            st[rs] += lazy[o] * (r - m);
            lazy[o] = 0;
        }
    }
    
    void Build(int o, int l, int r) {
        if(l == r)
            st[o] = a[l];
        else {
            int m = l + r >> 1;
            Build(lt);
            Build(rt);
            PushUp(o);
        }
        lazy[o] = 0;
    }
    
    void Update(int o, int l, int r, int ql, int qr, ll v) {
        if(ql <= l && r <= qr) {
            lazy[o] += v;
            st[o] += v * (r - l + 1);
            return;
        } else {
            PushDown(o, l, r);
            int m = l + r >> 1;
            if(ql <= m)
                Update(lt, ql, qr, v);
            if(qr >= m + 1)
                Update(rt, ql, qr, v);
            PushUp(o);
        }
    }
    
    ll Query(int o, int l, int r, int ql, int qr) {
        if(ql <= l && r <= qr) {
            return st[o];
        } else {
            PushDown(o, l, r);
            int m = l + r >> 1;
            ll res = 0;
            if(ql <= m)
                res = res + Query(lt, ql, qr);
            if(qr >= m + 1)
                res = res + Query(rt, ql, qr);
            return res;
        }
    }
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        int n, m;
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; ++i) {
            scanf("%d", &a[i]);
        }
        Build(1,1,n);
        int op, x, y, k;
        while(m--) {
            scanf("%d%d%d", &op, &x, &y);
            if(op == 1) {
                scanf("%d", &k);
                Update(1, 1, n, x, y, k);
            } else {
                printf("%lld
    ", Query(1, 1, n, x, y));
            }
        }
        return 0;
    }
    

    单点修改线段树:

    const int MAXM=100000;
    int a[MAXM+5];
    int st[(MAXM<<2)+5];
    
    inline void push_up(int o) {
        st[o]=st[o<<1]+st[o<<1|1];
    }
    
    void build(int o,int l,int r) {
        if(l==r){
            st[o]=a[l];
        }
        else {
            int m=(l+r)>>1;
            build(o<<1,l,m);
            build(o<<1|1,m+1,r);
            push_up(o);
        }
    }
    
    void update(int o,int l,int r,int x,int v) {
        if(l==r) {
            st[o]=v;
            return;
        } else {
            int m=(l+r)>>1;
            if(x<=m)
                update(o<<1,l,m,x,v);
            else if(x>=m+1)
                update(o<<1|1,m+1,r,x,v);
            push_up(o);
        }
    }
    
    int query(int o,int l,int r,int a,int b) {
        if(a<=l&&r<=b) {
            return st[o];
        } else {
            int m=(l+r)>>1;
            int ans=0;
            if(a<=m)
                ans=query(o<<1,l,m,a,b);
            if(b>=m+1)
                ans+=query(o<<1|1,m+1,r,a,b);
            return ans;
        }
    }
    

    需要注意lazy的更新顺序的区间修改线段树:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int MAXM = 100000 + 5;
    int a[MAXM];
    ll sum[MAXM << 2], add[MAXM << 2], mul[MAXM << 2];
    
    int mod;
    
    inline void push_up(int o) {
        sum[o] = (sum[o << 1] + sum[o << 1 | 1]) % mod;
    }
    
    inline void push_down(int o, int l, int r) {
        if(mul[o] != 1) {
            mul[o << 1] = mul[o << 1] * mul[o] % mod;
            mul[o << 1 | 1] = mul[o << 1 | 1] * mul[o] % mod;
            add[o << 1] = add[o << 1] * mul[o] % mod;
            add[o << 1 | 1] = add[o << 1 | 1] * mul[o] % mod;
            sum[o << 1] = sum[o << 1] * mul[o] % mod;
            sum[o << 1 | 1] = sum[o << 1 | 1] * mul[o] % mod;
            mul[o] = 1;
        }
        if(add[o] != 0) {
            add[o << 1] = (add[o << 1] + add[o]) % mod;
            add[o << 1 | 1] = (add[o << 1 | 1] + add[o]) % mod;
            int m = (l + r) >> 1;
            sum[o << 1] = (sum[o << 1]  + add[o] * (m - l + 1)) % mod;
            sum[o << 1 | 1] = (sum[o << 1 | 1] + add[o] * (r - m) ) % mod;
            add[o] = 0;
        }
    }
    
    void build(int o, int l, int r) {
        if(l == r)
            sum[o] = a[l];
        else {
            int m = (l + r) >> 1;
            build(o << 1, l, m);
            build(o << 1 | 1, m + 1, r);
            push_up(o);
        }
        mul[o] = 1, add[o] = 0;
    }
    
    void update_add(int o, int l, int r, int a, int b, ll v) {
        if(a <= l && r <= b) {
            add[o] = (add[o] + v) % mod;
            sum[o] = (sum[o] + v * (r - l + 1) % mod) % mod;
            return;
        } else {
            push_down(o, l, r);
            int m = (l + r) >> 1;
            if(a <= m)
                update_add(o << 1, l, m, a, b, v);
            if(b >= m + 1)
                update_add(o << 1 | 1, m + 1, r, a, b, v);
            push_up(o);
        }
    }
    
    void update_mul(int o, int l, int r, int a, int b, ll v) {
        if(a <= l && r <= b) {
            mul[o] = mul[o] * v % mod;
            add[o] = add[o] * v % mod;
            sum[o] = sum[o] * v % mod;
            return;
        } else {
            push_down(o, l, r);
            int m = (l + r) >> 1;
            if(a <= m)
                update_mul(o << 1, l, m, a, b, v);
            if(b >= m + 1)
                update_mul(o << 1 | 1, m + 1, r, a, b, v);
            push_up(o);
        }
    }
    
    ll query(int o, int l, int r, int a, int b) {
        if(a <= l && r <= b) {
            return sum[o];
        } else {
            push_down(o, l, r);
            int m = (l + r) >> 1;
            ll ans = 0;
            if(a <= m)
                ans = query(o << 1, l, m, a, b);
            if(b >= m + 1)
                ans = (ans + query(o << 1 | 1, m + 1, r, a, b)) % mod;
            return ans;
        }
    }
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        int n, m;
        scanf("%d%d%d", &n, &m, &mod);
        for(int i = 1; i <= n; ++i)
            scanf("%d", &a[i]);
        build(1, 1, n);
        for(int i = 1; i <= m; ++i) {
            int op, x, y;
            scanf("%d%d%d", &op, &x, &y);
            if(op == 1) {
                int k;
                scanf("%d", &k);
                update_mul(1, 1, n, x, y, k);
            } else if(op == 2) {
                int k;
                scanf("%d", &k);
                update_add(1, 1, n, x, y, k);
            } else {
                printf("%lld
    ", query(1, 1, n, x, y));
            }
        }
    }
    

    lazy标记互相影响的线段树,直接强制下推标记就不用这么多破事。但是要注意叶子是不能下推标记的。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    
    const int MAXN = 1e6;
    const int MAXLOGAI = 4;
    
    int a[MAXN + 5];
    int st[MAXN * 4 + 5][MAXLOGAI];
    char lazy[MAXN * 4 + 5][MAXLOGAI];
    
    inline void PushUp(int o) {
        for(int id = 0; id < MAXLOGAI; ++id)
            st[o][id] = st[o << 1][id] + st[o << 1 | 1][id];
    }
    
    inline void PushDown(int o, int l, int r) {
        //op=1 ^
        //op=2 |
        //op=3 &
        for(int id = 0; id < MAXLOGAI; ++id) {
            if(lazy[o][id]) {
                int mid = l + r >> 1;
                if(lazy[o][id] == 1) {
                    if(lazy[o << 1][id] == 0) {
                        st[o << 1][id] = (mid - l + 1) - st[o << 1][id];
                        lazy[o << 1][id] = 1;
                    } else if(lazy[o << 1][id] == 1) {
                        st[o << 1][id] = (mid - l + 1) - st[o << 1][id];
                        lazy[o << 1][id] = 0;
                    } else if(lazy[o << 1][id] == 2) {
                        st[o << 1][id] = 0;
                        lazy[o << 1][id] = 3;
                    } else if(lazy[o << 1][id] == 3) {
                        st[o << 1][id] = (mid - l + 1);
                        lazy[o << 1][id] = 2;
                    }
    
                    if(lazy[o << 1 | 1][id] == 0) {
                        st[o << 1 | 1][id] = (r - (mid + 1) + 1) - st[o << 1 | 1][id];
                        lazy[o << 1 | 1][id] = 1;
                    } else if(lazy[o << 1 | 1][id] == 1) {
                        st[o << 1 | 1][id] = (r - (mid + 1) + 1) - st[o << 1 | 1][id];
                        lazy[o << 1 | 1][id] = 0;
                    } else if(lazy[o << 1 | 1][id] == 2) {
                        st[o << 1 | 1][id] = 0;
                        lazy[o << 1 | 1][id] = 3;
                    } else if(lazy[o << 1 | 1][id] == 3) {
                        st[o << 1 | 1][id] = (r - (mid + 1) + 1);
                        lazy[o << 1 | 1][id] = 2;
                    }
                } else if(lazy[o][id] == 2) {
                    st[o << 1][id] = (mid - l + 1);
                    lazy[o << 1][id] = 2;
                    st[o << 1 | 1][id] = (r - (mid + 1) + 1);
                    lazy[o << 1 | 1][id] = 2;
                } else {
                    st[o << 1][id] = 0;
                    lazy[o << 1][id] = 3;
                    st[o << 1 | 1][id] = 0;
                    lazy[o << 1 | 1][id] = 3;
                }
                lazy[o][id] = 0;
            }
        }
    }
    
    void Build(int o, int l, int r) {
        for(int id = 0; id < MAXLOGAI; ++id)
            lazy[o][id] = 0;
        if(l == r) {
            for(int id = 0; id < MAXLOGAI; ++id)
                st[o][id] = (a[l] & (1 << id)) ? 1 : 0;
        } else {
            int mid = l + r >> 1;
            Build(o << 1, l, mid);
            Build(o << 1 | 1, mid + 1, r);
            PushUp(o);
        }
    }
    
    void Update(int o, int l, int r, int ql, int qr, int op, int x) {
        //op=1 ^
        //op=2 |
        //op=3 &
        if(l != r)
            PushDown(o, l, r);
        if(ql <= l && r <= qr) {
            if(op == 1) {
                for(int id = 0; id < MAXLOGAI; ++id) {
                    if(x & (1 << id)) {
                        st[o][id] = (r - l + 1) - st[o][id];
                        lazy[o][id] = op;
                    }
                }
            } else if(op == 2) {
                for(int id = 0; id < MAXLOGAI; ++id) {
                    if(x & (1 << id)) {
                        st[o][id] = (r - l + 1);
                        lazy[o][id] = op;
                    }
                }
            } else {
                for(int id = 0; id < MAXLOGAI; ++id) {
                    if(!(x & (1 << id))) {
                        st[o][id] = 0;
                        lazy[o][id] = op;
                    }
                }
            }
        } else {
            int mid = l + r >> 1;
            if(ql <= mid)
                Update(o << 1, l, mid, ql, qr, op, x);
            if(qr >= mid + 1)
                Update(o << 1 | 1, mid + 1, r, ql, qr, op, x);
            PushUp(o);
        }
    }
    
    ll Query(int o, int l, int r, int ql, int qr) {
        if(l != r)
            PushDown(o, l, r);
        if(ql <= l && r <= qr) {
            ll res = 0;
            for(int id = 0; id < MAXLOGAI; ++id)
                res += 1ll * (1 << id) * (st[o][id]);
            return res;
        } else {
            ll res = 0;
            int mid = l + r >> 1;
            if(ql <= mid)
                res += Query(o << 1, l, mid, ql, qr);
            if(qr >= mid + 1)
                res += Query(o << 1 | 1, mid + 1, r, ql, qr);
            return res;
        }
    }
    
    int main() {
    #ifdef localll
        freopen("lyz.in", "r", stdin);
    #endif // local
        int T, n, m;
        scanf("%d", &T);
        while(T--) {
            scanf("%d%d", &n, &m);
            for(int i = 1; i <= n; ++i)
                scanf("%d", &a[i]);
            Build(1, 1, n);
            for(int i = 1; i <= m; ++i) {
                char ops[10];
                int l, r, x;
                scanf("%s", ops);
                if(ops[0] == 'S') {
                    scanf("%d%d", &l, &r);
                    ++l, ++r;
                    printf("%lld
    ", Query(1, 1, n, l, r));
                } else {
                    scanf("%d%d%d", &x, &l, &r);
                    ++l, ++r;
                    if(ops[0] == 'X') {
                        Update(1, 1, n, l, r, 1, x);
                    } else if(ops[0] == 'O') {
                        Update(1, 1, n, l, r, 2, x);
                    } else if(ops[0] == 'A') {
                        Update(1, 1, n, l, r, 3, x);
                    }
                }
            }
        }
    }
    
  • 相关阅读:
    iOS开发代码规范
    数组去重方法总结
    iOS进阶学习-网络之数据安全
    OC 动态类型,动态绑定,动态加载
    ios运行某些工程时屏幕上下出现黑边的解决办法
    流程控制和数组(关于JAVA基础注意事项)
    高级函数
    源码
    sql s2 学期的学习
    Java 学习笔记
  • 原文地址:https://www.cnblogs.com/Inko/p/11404072.html
Copyright © 2011-2022 走看看