zoukankan      html  css  js  c++  java
  • 线段树模板

    这一部分的功能和树状数组一样,这里是树状数组的模板
    除了求和之外,还能解决区间最小最大值,区间染色

    1 单点修改,区间查询

    P3374 【模板】树状数组 1

    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    const int maxn = 5e5 + 10;
    struct node{
        int l,r;
        int sum;
    }tree[maxn * 4];
    int n,m,a[maxn];
    
    void build(int i,int l,int r){
        tree[i].l = l; tree[i].r = r;
        if(l==r){
            tree[i].sum = a[l];
            return;
        }
        int mid = (l + r)/ 2;
        build(i * 2,l,mid);
        build(i * 2 + 1,mid + 1,r);
        tree[i].sum = tree[i * 2].sum + tree[i * 2 + 1].sum;
    }
    //区间查询
    int search(int i,int l,int r){
        //这个区间被完全包括在目标区间里面,返回这个区间的值
        if(tree[i].l >= l && tree[i].r <= r)
            return tree[i].sum;
        //这个区间和目标区间不相干
        if(tree[i].l > r || tree[i].r < l)
            return 0;
        int s = 0;
        //这个区间的左儿子和目标区间有交集
        if(tree[i * 2].r >= l)
            s += search(i * 2,l,r);
        //这个区间的右儿子和目标区间有交集
        if(tree[i * 2 + 1].l <= r)
            s += search(i * 2 + 1,l,r);
        return s;
    }
    
    //单点修改
     void add(int i ,int dis,int k){
        //如果是叶子节点,则说明找到了
        if(tree[i].l == tree[i].r){
            tree[i].sum += k;
            return;
        }
        if(dis <= tree[i * 2].r)
            add(i * 2,dis,k);
        else add(i * 2 + 1,dis,k);
        tree[i].sum = tree[i * 2].sum + tree[i * 2 + 1].sum;
    
        return;
    }
    signed main(){
        //freopen("in","r",stdin);
        ios::sync_with_stdio(0);
        cin >> n >> m;
        for(int i = 1; i <= n; i++) cin >> a[i];
        build(1,1,n);
        while(m--){
            int op,x,y;
            cin >> op >> x >> y;
            if(op == 1) add(1,x,y);
            else cout << search(1,x,y) << endl;
        }
        return 0;
    }
    View Code

    2 区间修改,单点查询

    P3368 【模板】树状数组 2

    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    const int maxn = 5e5 + 10;
    struct node{
        int l,r;
        int sum;
    }tree[maxn * 4];
    int n,m,a[maxn];
    int ans;
    void build(int i,int l,int r){
        tree[i].sum = 0;
        tree[i].l = l; tree[i].r = r;
        if(l==r) return;
        int mid = (l + r)/ 2;
        build(i * 2,l,mid);
        build(i * 2 + 1,mid + 1,r);
        tree[i].sum = tree[i * 2].sum + tree[i * 2 + 1].sum;
    }
    
    void search(int i,int dis){
        ans += tree[i].sum;
        if(tree[i].l == tree[i].r)
            return;
        if(dis <= tree[i * 2].r)
            search(i * 2,dis);
        if(dis >= tree[i * 2 + 1].l)
            search(i * 2 + 1,dis);
    }
    void add(int i ,int l,int r,int k){
        if(tree[i].l >= l && tree[i].r <= r){
            tree[i].sum += k;
            return;
        }
        if(tree[i * 2].r >= l) add(i * 2,l,r,k);
        if(tree[i * 2 + 1].l <= r) add(i * 2 + 1,l,r,k);
    }
    signed main(){
        //freopen("in","r",stdin);
        ios::sync_with_stdio(0);
        cin >> n >> m;
        for(int i = 1; i <= n; i++) cin >> a[i];
        build(1,1,n);
        while(m--){
            int op,x,y,k;
            cin >> op;
            if(op == 1) {
                cin >> x >> y >> k;
                add(1,x,y,k);
            }
            else {
                cin >> x;
                ans = 0;
                search(1,x);
                cout << ans + a[x] << endl;
            }
        }
        return 0;
    }
    View Code

     进阶线段树(区间加减)

    区间修改 区间查询

    区间修改

    //把自己的lazytage归零,并且给自己的儿子加上
    void pushdown(int i){
        if(tree[i].lz){
            tree[i * 2].lz += tree[i].lz;//左右儿子分别加上父亲的lz
            tree[i * 2 + 1].lz += tree[i].lz;
            int mid = (tree[i].l + tree[i].r)/ 2;
            //左右分别加起来
            tree[i * 2].sum  += tree[i].lz *(mid - tree[i * 2].l + 1);
            tree[i * 2 + 1].sum += tree[i].lz * (tree[i * 2 + 1].r - mid);
            tree[i].lz = 0;//父亲lz归0
        }
        return;
    }
    View Code
    
    //区间修改(数据更新)
    void add(int i ,int l,int r,int k){
        //如果这个区间完全包括在目标区间内
        if(tree[i].l >= l && tree[i].r <= r){
            tree[i].sum += k*(tree[i].r - tree[i].l + 1);
            tree[i].lz += k;//记录lazytage
            return;
        }
        pushdown(i);//向下传递
        if(tree[i * 2].r >= l) add(i * 2,l,r,k);
        if(tree[i * 2 + 1].l <= r) add(i * 2 + 1,l,r,k);
        tree[i].sum = tree[i * 2].sum + tree[i * 2 + 1].sum;
        return;
    }
    View Code

    区间查询

    int search(int i,int l,int r){
        if(tree[i].l >= l && tree[i].r <= r)
            return tree[i].sum;
        if(tree[i].r < l || tree[i].l > r)
            return 0;
        pushdown(i);
        int s = 0;
        if(tree[i * 2].r >= l) s += search(i * 2,l,r);
        if(tree[i * 2 + 1].l <= r) s += search(i * 2 + 1,l,r);
        return s;
    }
    View Code

    P3372 【模板】线段树 1

    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    const int maxn = 5e5 + 10;
    struct node{
        int l,r;
        int sum;
        int lz;//lazytage
    }tree[maxn * 4];
    int n,m,a[maxn];
    void build(int i,int l,int r){
        tree[i].lz = 0;
        tree[i].l = l; tree[i].r = r;
        if(l==r){
            tree[i].sum = a[l];
            return;
        }
        int mid = (l + r)/ 2;
        build(i * 2,l,mid);
        build(i * 2 + 1,mid + 1,r);
        tree[i].sum = tree[i * 2].sum + tree[i * 2 + 1].sum;
    }
    //把自己的lazytage归零,并且给自己的儿子加上
    void pushdown(int i){
        if(tree[i].lz){
            tree[i * 2].lz += tree[i].lz;//左右儿子分别加上父亲的lz
            tree[i * 2 + 1].lz += tree[i].lz;
            int mid = (tree[i].l + tree[i].r)/ 2;
            //左右分别加起来
            tree[i * 2].sum  += tree[i].lz *(mid - tree[i * 2].l + 1);
            tree[i * 2 + 1].sum += tree[i].lz * (tree[i * 2 + 1].r - mid);
            tree[i].lz = 0;//父亲lz归0
        }
        return;
    }
    //区间修改(数据更新)
    void add(int i ,int l,int r,int k){
        //如果这个区间完全包括在目标区间内
        if(tree[i].l >= l && tree[i].r <= r){
            tree[i].sum += k*(tree[i].r - tree[i].l + 1);
            tree[i].lz += k;//记录lazytage
            return;
        }
        pushdown(i);//向下传递
        if(tree[i * 2].r >= l) add(i * 2,l,r,k);
        if(tree[i * 2 + 1].l <= r) add(i * 2 + 1,l,r,k);
        tree[i].sum = tree[i * 2].sum + tree[i * 2 + 1].sum;
        return;
    }
    int search(int i,int l,int r){
        if(tree[i].l >= l && tree[i].r <= r)
            return tree[i].sum;
        if(tree[i].r < l || tree[i].l > r)
            return 0;
        pushdown(i);
        int s = 0;
        if(tree[i * 2].r >= l) s += search(i * 2,l,r);
        if(tree[i * 2 + 1].l <= r) s += search(i * 2 + 1,l,r);
        return s;
    }
    signed main(){
        //freopen("in","r",stdin);
        ios::sync_with_stdio(0);
        cin >> n >> m;
        for(int i = 1; i <= n; i++) cin >> a[i];
        build(1,1,n);
        while(m--){
            int op,x,y,k;
            cin >> op;
            if(op == 1) {
                cin >> x >> y >> k;
                add(1,x,y,k);
            }
            else {
                cin >> x >> y;
                cout << search(1,x,y) << endl;
            }
        }
        return 0;
    }
    View Code

    乘法/sqrt线段树

    P3373 【模板】线段树 2

    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    const int maxn = 5e5 + 10;
    struct node{
        int l,r;
        int sum;
        int plz,mlz;//lazytage分为两种,加法plz 乘法 mlz
    }tree[maxn * 4];
    int n,m,p,a[maxn];
    void build(int i,int l,int r){
        tree[i].mlz = 1;
        tree[i].l = l; tree[i].r = r;
        if(l==r){
            tree[i].sum = a[l] % p;
            return;
        }
        int mid = (l + r)/ 2;
        build(i * 2,l,mid);
        build(i * 2 + 1,mid + 1,r);
        tree[i].sum = (tree[i * 2].sum + tree[i * 2 + 1].sum) % p;
        return;
    }
    
    void pushdown(int i){
        int k1=tree[i].mlz,k2=tree[i].plz;
        tree[i * 2].sum=(tree[i * 2].sum*k1 + k2* (tree[i * 2].r - tree[i * 2].l+1))%p;
        tree[i * 2 + 1].sum=(tree[i * 2 + 1].sum * k1+k2*(tree[i * 2 + 1].r-tree[i * 2 + 1].l + 1))%p;
        tree[i * 2].mlz=(tree[i * 2].mlz*k1)%p;
        tree[i * 2 + 1].mlz=(tree[i * 2 + 1].mlz*k1)%p;
        tree[i * 2].plz=( tree[i * 2].plz *k1 + k2)%p;
        tree[i * 2 + 1].plz=(tree[i * 2 + 1].plz * k1 + k2)%p;
        tree[i].plz=0;
        tree[i].mlz=1;
        return ;
    }
    
    void mul(int i ,int l,int r,int k){
        if(tree[i].r < l || tree[i].l > r)
            return ;
        //如果这个区间完全包括在目标区间内
        if(tree[i].l >= l && tree[i].r <= r){
            tree[i].sum = ( k * tree[i].sum) % p;
            tree[i].mlz = (tree[i].mlz * k) % p;
            tree[i].plz = (tree[i].plz * k) % p;
            return;
        }
        pushdown(i);//向下传递
        if(tree[i * 2].r >= l) mul(i * 2,l,r,k);
        if(tree[i * 2 + 1].l <= r) mul(i * 2 + 1,l,r,k);
        tree[i].sum = (tree[i * 2].sum + tree[i * 2 + 1].sum) % p;
        return;
    }
    
    void add(int i ,int l,int r,int k){
        if(tree[i].r < l || tree[i].l > r)
            return ;
        //如果这个区间完全包括在目标区间内
        if(tree[i].l >= l && tree[i].r <= r){
            tree[i].sum += (k *(tree[i].r - tree[i].l + 1)) % p;
            tree[i].plz = (tree[i].plz + k) % p;
            return;
        }
        pushdown(i);//向下传递
        if(tree[i * 2].r >= l) add(i * 2,l,r,k);
        if(tree[i * 2 + 1].l <= r) add(i * 2 + 1,l,r,k);
        tree[i].sum = (tree[i * 2].sum + tree[i * 2 + 1].sum) % p;
        return;
    }
    int search(int i,int l,int r){
        if(tree[i].r < l || tree[i].l > r)
            return 0;
        if(tree[i].l >= l && tree[i].r <= r)
            return tree[i].sum;
        pushdown(i);
        int s = 0;
        if(tree[i * 2].r >= l) s += search(i * 2,l,r) % p;
        if(tree[i * 2 + 1].l <= r) s += search(i * 2 + 1,l,r) % p;
        return s % p;
    }
    signed main(){
       // freopen("in","r",stdin);
        ios::sync_with_stdio(0);
        cin >> n >> m >> p;
        for(int i = 1; i <= n; i++) cin >> a[i];
        build(1,1,n);
        while(m--){
            int op,x,y,k;
            cin >> op;
            if(op == 1) {
                cin >> x >> y >> k;
                k %= p;
                mul(1,x,y,k);
            }
            else if(op == 2){
                cin >> x >> y >> k;
                k %= p;
                add(1,x,y,k);
            }else{
                cin >> x >> y;
                cout << search(1,x,y) << endl;
            }
        }
        return 0;
    }
    View Code

    大佬的博客

  • 相关阅读:
    调用其他类的方法
    CString中 format、trimLeft和trimright、trim 和FindOneOf用法
    GetAsyncKeyState()& 0x8000
    C++打开剪切板,获取剪切板数据
    CString比较不区分大小写
    C++ string中find() 用法
    CString数组和CStringArray
    nested exception is java.io.FileNotFoundException: Could not open ServletContext resource
    SQLPlus获取oracle表操作SQL
    XShell实现服务器端文件的上传下载
  • 原文地址:https://www.cnblogs.com/xcfxcf/p/12301570.html
Copyright © 2011-2022 走看看