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

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    
    using namespace std;
    
    typedef long long LL;
    const int maxn=1e5+7;
    
    int a[maxn],tree[maxn*4];
    int lz[maxn*4];
    
    void build(int node ,int start, int endd)
    {
        if(start == endd)//叶子节点
        {
            tree[node] = a[start];
            return ;
        }
        else{
            int mid  = start + ((endd - start) >> 1);
            int lson = node << 1 ;//左儿子:2 * node
            int rson = (node << 1) | 1;//右儿子:2 * node + 1
            build(lson, start, mid);
            build(rson, mid+1, endd);
            tree[node] = tree[lson] + tree[rson];
        }
    }
    
    //单点更新,idx为需要更新的叶子节点编号,add为更改值
    void update(int node, int start, int endd, int idx, int instead)
    {
        if(start == endd)
        {
            tree[start] = instead;
            return ;
        }
        else
        {
            int mid  = start + (endd - start) >> 1;
            int lson = (node << 1);
            int rson = (node << 1) | 1;
            if( idx <= mid)
            {
                update(lson, start, mid, idx, instead);
            }
            else
            {
                update(rson, mid+1, endd, idx, instead);
            }
            tree[node] = tree[lson] + tree[rson];
        }
    }
    
    
    //单点查询
    
    LL query(LL node,LL l,LL r,LL x)
    {
    	if(l==r&&l==x) return tree[num];
    	LL mid=(l+r)>>1,tmp;
    	if(x<=mid) tmp=query(num*2,l,mid,x);
    	else tmp=query(num*2+1,mid+1,r,x);
    	return tmp+tree[num];
    }
    
    LL query(int node, int start, int endd, int l, int r)
    {
        LL sum=0;
        if(l>endd || r<start)
        {
            return 0;
        }
        if(l<=start && r>=endd)
        {
            return tree[node];
        }
        int mid  = start + (endd - start) >> 1;
        int lson =  node << 1;
        int rson = (node << 1) | 1;
        LL sum_left  = query(lson, start, mid,  l, r);
        LL sum_right = query(rson, mid+1, endd, l, r);
        sum = sum_left + sum_right;
    
        return sum;
    }
    
    ------------------------------------------------------------------------------
    
    //区间加值
    void push_up(int node)
    {
        tree[node] = tree[node<<1] + tree[(node<<1)|1];
    }
    
    void push_down(int node, int l, int r)
    {
        int lson = (node << 1);
        int rson = (node << 1) | 1;
        if(lz[node])
        {
            lz[lson]   =  lz[node];
            lz[rson]   =  lz[node];
            int mid    =  l + (r - l) >> 1;
            tree[lson] += lz[node] * (mid-l+1);
            tree[rson] += lz[node] * (r-mid);
    
            lz[node]   =  0; //lazy标记使用完后需清零
    
        }
    }
    
    void update(int node, int start, int endd, int l, int r, int add)
    {
        if(l<=start && r>=endd)//当前结点被所查询的区间覆盖
        {
            lz[node]   += add; //更新该结点所需的更新信息
            tree[node] += add * (r-l+1);//更新该结点信息
            return ;   //lazy只需记录到当前结点
        }
    
        push_down(node, start, endd);
        int mid = start + ((endd - start)>>1);int mid = l + ((r-l)>>1);
        if(l <= mid) update( node<<1, start, mid, l, r, add);
        if(r >= mid) update( (node<<1)|1, mid+1, endd, l, r, add);
        push_up(node);//向上递归时需一步一步更新回父节点
    
    }
    
    LL query(int node, int start, int endd, int l, int r)
    {
        if(l <= start && r>=endd)
        {
            return tree[node];
        }
        push_down(node, start, endd);
        int mid = start + ((endd - start)>>1);
        LL ans = 0;
        if(l <= mid)   ans += query( node<<1, start, mid, l, r);
        if(r >= mid+1) ans += query( node<<1|1, mid+1, endd, l, r);
    
        return ans;
    }
    
    ------------------------------------------------------------------------------
    
    //区间改值
    
    void pushup(int node)
    {
        tree[node] = tree[node<<1] + tree[node<<1|1];
    }
    
    void pushdown(int node, int start, int endd)
    {
        if(lz[node])
        {
            int c = lz[node];
            lz[node<<1]   = c;
            lz[node<<1|1] = c;
            int mid = start + ((endd - start)>>1);
            tree[node<<1] = (mid-start+1) * c;
            tree[node<<1] = (endd-mid) * c;
            lz[node] = 0;
        }
    }
    
    void update(int node, int start, int endd, int l, int r,int c)
    {
        if(l <= start && r >= endd)
        {
            lz[node] = c;
            tree[node] = (endd-start+1) * c;
            return ;
        }
        pushdown(node, start, endd);
        int mid = start + ((endd - start)>>1);
        if(l <= mid) update(node<<1, start, mid, l, r, c);
        if(r >= mid+1) update(node<<1|1, mid+1, endd, l, r,c);
        pushup(node);
    }
    
    LL query(int node, int start, int endd, int l, int r)
    {
        if(l <= start && r >= endd)
        {
            return tree[node];
        }
        pushdown(node, start, endd);
        int mid = start + ((endd-start)>>1);
        LL ans=0;
        if(l <= mid) ans+=query(node<<1, start, mid, l, r);
        if(r >= mid+1) ans+=query(node<<1|1, mid+1, endd, l, r);
        return ans;
    }
    
    int main()
    {
        int q=1;
        for(int i=1;i<=6;i++)
        {
            a[i]=q++;
        }
        build(1,1,6);
        for(int i=1;i<=15;i++)
        {
            printf("tree[%d]:%d
    ",i,tree[i]);
        }
        return 0;
    }
    --------------------------------------------------------------------------------------
    //求区间最大值
    
    void update(int o,int l,int r,int ind,int ans){  //o、l、r为当前更新到的结点、左右端点,ind为需要修改的叶子结点左端点,ans为需要修改成的值;
        if(l==r){                      //若当前更新点的左右端点相等即到叶子结点时,直接更新信息并返回
            st[o]=ans;
            return;
        }
        int m=l+((r-l)>>1);
        if(ind<=m){                      //若需要更新的叶子结点在当前结点的左儿子结点的范围内,则递归更新左儿子结点,否则更新右儿子结点
            update(o<<1,l,m,ind,ans);
        }
        else{
            update((o<<1)|1,m+1,r,ind,ans);
        }
        st[o]=max(st[o<<1],st[(o<<1)|1]);//递归回之后用儿子结点更新父节点(此处是区间最大值)
    }
    
    {                               //在main函数中的语句
            update(1,1,n,ind,ans);
    }
    
    int query(int o,int l,int r,int ql,int qr){      //ql、qr为需要查询的区间左右端点
        if(ql>r||qr<l) return -1;              //若当前结点和需要查找的区间不相交,则返回一个对于区间查询无关的值(如求和时返回0,求最大值时返回-1等)
        if(ql<=l&&qr>=r) return st[o];        //若当前结点的区间被需要查询的区间覆盖,则返回当前结点的信息
        int m=l+((r-l)>>1);
        int p1=query(o<<1,l,m,ql,qr),p2=query((o<<1)|1,m+1,r,ql,qr);  //p1为查询左儿子结点得到的信息,p2为查询右儿子结点得到的信息
        return max(p1,p2);    //综合两个儿子结点的信息并返回
    }
    
    {    //main函数中的语句
            printf("%d
    ",query(1,1,n,a,b));
    }
    
  • 相关阅读:
    MFC和Qt优缺点 (MFC几乎没有优点、全面下风)
    获得WIN7管理员权限(可通过修改注册表,或者组策略改变)
    tolua#是Unity静态绑定lua的一个解决方案
    C#实现拼图游戏
    FastDFS分布式文件系统
    生成动态Lambda表达式1
    Azure IoT
    SignalR
    延迟队列功能
    监控知识体系
  • 原文地址:https://www.cnblogs.com/orangeko/p/11367807.html
Copyright © 2011-2022 走看看