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

    线段树

    标签(空格分隔): @zhshh 线段树


    双标记模板

    为什么会有这个?
    因为如果看了最后面的代码,会发现有很多用到了(root<<1)+1等等的结构
    而C++的#define恰好可以方便的解决

    定义列表
    cnt 当前树
    lt 左子树
    rt 右子树
    lr 左子树的下标
    rr 右子树的下标
    ci const int
    LL long long

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #define cnt tree[root]
    #define lr (root<<1)
    #define rr ((root<<1)+1)
    #define lt tree[lr]
    #define rt tree[rr]
    #define ci const int
    #define MAX (100000+10)
    #define LL long long
    using namespace std;
    struct node{
        int left,right;
        LL add,mul,val;
        node(){
            mul=1;
            add=0;
        }
    }tree[MAX<<2];
    LL a[MAX];
    int n;
    LL mod;
    void pushup(ci root){
        cnt.val=lt.val+rt.val;
    }
    void pushdown(ci root){
        if(cnt.mul!=1 || cnt.add!=0){
            lt.val=(lt.val*cnt.mul)%mod;
            lt.val=(lt.val+cnt.add*(lt.right-lt.left+1))%mod;
            lt.add=(lt.add*cnt.mul)%mod;
            lt.add=(lt.add+cnt.add)%mod;
            lt.mul=(lt.mul*cnt.mul)%mod;
    
            rt.val=(rt.val*cnt.mul)%mod;
            rt.val=(rt.val+cnt.add*(rt.right-rt.left+1))%mod;
            rt.add=(rt.add*cnt.mul)%mod;
            rt.add=(rt.add+cnt.add)%mod;
            rt.mul=(rt.mul*cnt.mul)%mod;
    
            cnt.mul=1;
            cnt.add=0;
        }
    }
    void mul(ci root,ci left,ci right,ci k){
        if(left<=cnt.left && right>=cnt.right){
            cnt.mul=(cnt.mul*k)%mod;
            cnt.add=(cnt.add*k)%mod;
            cnt.val=(cnt.val*k)%mod;
            return ;
        }
        pushdown(root);
        int mid=(cnt.left+cnt.right)>>1;
        if(left<=mid)mul(lr,left,right,k);
        if(right>mid)mul(rr,left,right,k);
        pushup(root);
    }
    void add(ci root,ci left,ci right,ci c){
        if(left<=cnt.left && right>=cnt.right){
            cnt.add=(cnt.add+c)%mod;
            cnt.val=(cnt.val+c*(cnt.right-cnt.left+1))%mod;
            return ;
        }
        pushdown(root);
        int mid=(cnt.left+cnt.right)>>1;
        if(left<=mid)add(lr,left,right,c);
        if(right>mid)add(rr,left,right,c);
        pushup(root);
        return ;
    }
    LL query(ci root,ci left,ci right){
        if(left<=cnt.left && right>=cnt.right){
            return cnt.val;
        }
        pushdown(root);
        int mid=(cnt.left+cnt.right)>>1;
        LL ans=0;
        if(left<=mid)ans=(ans+query(lr,left,right))%mod;
        if(right>mid)ans=(ans+query(rr,left,right))%mod;
        return ans;
    }
    void build(ci root,ci left,ci right){
        cnt.left=left;
        cnt.right=right;
        if(left==right){
            cnt.val=a[left];
            return ;
        }
        int mid=(cnt.left+cnt.right)>>1;
        build(lr,left,mid);
        build(rr,mid+1,right);
        pushup(root);
        return ;
    }
    void pr(){
        for(int i=1;i<=n;i++){
            printf("%3d%7d\n",i,query(1,i,i));
        }
        cout<<endl;
    }
    int main(){
    //    freopen("in.txt","r",stdin);
        int m,t1,t2,t3;
        cin>>n>>m>>mod;
        for(int i=1;i<=n;i++){
            cin>>a[i];
            a[i]%=mod;
        }
        build(1,1,n);
        for(int i=1;i<=m;i++){
            cin>>t1;
            if(t1==1){
                cin>>t1>>t2>>t3;
                mul(1,t1,t2,t3);
            }else{
                if(t1==2){
                    cin>>t1>>t2>>t3;
                    add(1,t1,t2,t3);
                }else{
                    cin>>t1>>t2;
                    cout<<query(1,t1,t2)<<endl;
                }
            }
        }
        pr(); 
    }
    

    单标记

    洛谷P3372 【模板】线段树 1

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #define MAX 100000+10
    using namespace std;
    
    int n, m;
    struct node {
        int left, right;
        long long x, mark;
    } tree[MAX<<2];
    int a [MAX];
    void pushup(int root)
    {
        tree[root].x = tree[root * 2].x + tree[root * 2 + 1].x;
    }
    
    void pushdown(int root,int d)
    {
        if (tree[root].mark) {
            tree[root * 2].x += tree[root].mark*(d-d/2);
            tree[root * 2 + 1].x += tree[root].mark*(d/2);
            tree[root * 2].mark += tree[root].mark;
            tree[root * 2 + 1].mark += tree[root].mark;
            tree[root].mark = 0;
        }
    }
    
    void update(int left, int right, int c, int root)
    {
        if (left <= tree[root].left && right >= tree[root].right) {
            tree[root].mark += c;
            tree[root].x += (tree[root].right - tree[root].left + 1) * c;
            return;
        }
        pushdown(root, tree[root].right - tree[root].left + 1);
        int mid = (tree[root].left + tree[root].right) / 2;
        if (left <= mid)
            update(left, right, c, root * 2);
        if (right > mid)
            update(left, right, c, root * 2 + 1);
        pushup(root);
    }
    
    long long query(int left, int right, int root)
    {
        if (left <= tree[root].left && right >= tree[root].right)
            return tree[root].x;
        pushdown(root, tree[root].right - tree[root].left + 1);
        int mid = (tree[root].left + tree[root].right) / 2;
        long long ans = 0;
        if (left <= mid)
            ans += query(left, right, root * 2);
        if (right > mid)
            ans += query(left, right, 2 * root + 1);
        return ans;
    }
    
    void build (int root,int left,int right)
    {
        tree[root].left=left;
        tree[root].right=right;
        if(left==right) {
            tree[root].x=a[left];
        } else {
            int mid=(left+right)/2;
            build(2*root,left,mid);
            build(2*root+1,mid+1,right);
            tree[root].x=tree[2*root].x+tree[2*root+1].x;
        }
    
    }
    int main()
    {
    //	freopen("al1.txt","r",stdin);
        cin>>n>>m;
        for(int i=1; i<=n; i++)cin>>a[i];
        build(1,1,n);
        int ope;
        int q1,q2,q3;
        for(int qwe=1; qwe<=m; qwe++) {
            //	for(int i=1;i<=n;i++)cout<<query(i,i,1)<<"~";
            //	cout<<endl;
            cin>>ope;
            if(ope==1) {
                cin>>q1>>q2>>q3;
                update(q1,q2,q3,1);
            } else {
                cin>>q1>>q2;
                cout<<query(q1,q2,1);
                cout<<endl;
            }
        }
    }
    

    双标记

    洛谷P3373 【模板】线段树 2

    #include <iostream>
    #include <cstdio>
    #define LL unsigned long long
    #define MAX 100010
    using namespace std;
    struct node {
        int left,right;
        LL add,mul,val;
        node(){
            mul=1;
            add=0;
        }
    }tree[MAX<<2];
    LL a[MAX];
    int n;
    LL mod;
    void pushup(const int root){
        tree[root].val=(tree[root*2].val+tree[root*2+1].val);
    }
    void pushdown(const int root){
        if(tree[root].mul!=1 || tree[root].add!=0){
            tree[root<<1].val=(tree[root<<1].val*tree[root].mul)%mod;
            tree[root<<1].val=(tree[root<<1].val+tree[root].add*(tree[root<<1].right-tree[root<<1].left+1))%mod;
            tree[root<<1].add=(tree[root<<1].add*tree[root].mul)%mod;
            tree[root<<1].add=(tree[root<<1].add+tree[root].add)%mod;
            tree[root<<1].mul=(tree[root<<1].mul*tree[root].mul)%mod;
            
            tree[(root<<1)+1].val=(tree[(root<<1)+1].val*tree[root].mul)%mod;
            tree[(root<<1)+1].val=(tree[(root<<1)+1].val+tree[root].add*(tree[(root<<1)+1].right-tree[(root<<1)+1].left+1))%mod;
            tree[(root<<1)+1].add=(tree[(root<<1)+1].add*tree[root].mul)%mod;
            tree[(root<<1)+1].add=(tree[(root<<1)+1].add+tree[root].add)%mod;
            tree[(root<<1)+1].mul=(tree[(root<<1)+1].mul*tree[root].mul)%mod;
            
            tree[root].mul=1;
            tree[root].add=0;
        }
    }
    void add(const int root,const int left,const int right,	const int c){
        if(left<=tree[root].left && right>=tree[root].right){
            tree[root].add=(tree[root].add+c)%mod;
            tree[root].val=(tree[root].val+c*(tree[root].right-tree[root].left+1))%mod;
            return ;
        }
        pushdown(root);
        int mid=(tree[root].left+tree[root].right)/2;
        if(left<=mid)add(root*2,left,right,c);
        if(right>mid)add(root*2+1,left,right,c);
        pushup(root);
        return ;
    }
    void mul(const int root,const int left,const int right,const int k){
        if(left<=tree[root].left && right>=tree[root].right){
            tree[root].mul=(tree[root].mul*k)%mod;
            tree[root].add=(tree[root].add*k)%mod;
            tree[root].val=(tree[root].val*k)%mod;
            return ;
        }
        pushdown(root);
        int mid=(tree[root].left+tree[root].right)/2;
        if(left<=mid)mul(root*2,left,right,k);
        if(right>mid)mul(root*2+1,left,right,k);
        pushup(root);
        return ;
    }
    int query(const int root,const int left,const int right){
        if(left<=tree[root].left && right>=tree[root].right){
            return tree[root].val;
        }
        pushdown(root);
        int mid=(tree[root].left+tree[root].right)/2;
        LL ans=0;
        if(left<=mid)ans=(ans+query(root*2,left,right))%mod;
        if(right>mid)ans=(ans+query(root*2+1,left,right))%mod;
        return ans;
    }
    void build(const int root,const int left,const int right){
        tree[root].left=left;
        tree[root].right=right;
        if(left==right){
            tree[root].val=a[left];
            return ;
        }
        int mid=(tree[root].left+tree[root].right)/2;
        build(root*2,left,mid);
        build(root*2+1,mid+1,right);
        pushup(root);
        return ;
    }
    void pr(){
    	for(int i=1;i<=n;i++){
    		cout<<query(1,i,i)<<endl;
    	}
    	cout<<endl;
    }
    int main(){
        int m,t1,t2,t3;
        cin>>n>>m>>mod;
        for(int i=1;i<=n;i++){
            cin>>a[i];
            a[i]%=mod;
        }
        build(1,1,n);
        for(int i=1;i<=m;i++){
            cin>>t1;
            if(t1==1){
                cin>>t1>>t2>>t3;
                mul(1,t1,t2,t3);
            }else{
                if(t1==2){
                    cin>>t1>>t2>>t3;
                    add(1,t1,t2,t3);
                }else{
                    cin>>t1>>t2;
                    cout<<query(1,t1,t2)<<endl;
                }
            }
        }
    }
    
  • 相关阅读:
    Java IO流-NIO简介
    Java IO流-Properties
    Java IO流-序列化流和反序列化流
    Codeforces Round #371 (Div. 1) C
    bzoj 2326 矩阵快速幂
    IndiaHacks 2016
    HDU
    Educational Codeforces Round 51 (Rated for Div. 2) F
    Codeforces Round #345 (Div. 1) D
    Codeforces Round #300 E
  • 原文地址:https://www.cnblogs.com/zhshh/p/Segment_Tree.html
Copyright © 2011-2022 走看看