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

    c.单点更新

    /*
    线段树
    单点更新
    */
    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    
    #define L(root) ((root)<<1)
    #define R(root) (((root)<<1)|1)
    
    const int MAXN=1024;//
    int numbers[MAXN];//初始值
    
    struct node{
        int left,right;//
        int sum;
        int mid(){
            return left+((right-left)>>1);
        }
    }tree[MAXN*4];//4倍空间
    
    void pushUp(int root){
        tree[root].sum=tree[L(root)].sum+tree[R(root)].sum;
    }
    
    void build(int root,int left,int right){
        tree[root].left=left;
        tree[root].right=right;
        if(left==right){
            tree[root].sum=numbers[left];
            return;
        }
        int mid=tree[root].mid();
        build(L(root),left,mid);
        build(R(root),mid+1,right);
        pushUp(root);
    }
    
    int query(int root,int left,int right){
        if(tree[root].left==left&&tree[root].right==right){
            return tree[root].sum;
        }
        int mid=tree[root].mid();
        if(right<=mid){
            return query(L(root),left,right);
        }
        else if(left>mid){
            return query(R(root),left,right);
        }
        else{
            return query(L(root),left,mid)+query(R(root),mid+1,right);
        }
    }
    
    void update(int root,int pos,int add){
        if(tree[root].left==tree[root].right){
            tree[root].sum+=add;
            return;
        }
        int mid=tree[root].mid();
        if(pos<=mid){
            update(L(root),pos,add);
        }
        else{
            update(R(root),pos,add);
        }
        pushUp(root);
    }
    
    int main(){
    
        memset(numbers,0,sizeof(numbers));
    
        int i;
        for(i=1;i<MAXN;++i){
            numbers[i]=i;
        }
    
        build(1,1,10);
    
        cout<<query(1,2,3)<<endl;
    
        update(1,2,100);
        cout<<query(1,2,3)<<endl;
    
        return 0;
    }
    View Code

    c'.单点更新,写法与c稍有差异,要理解

    /*
    线段树
    单点更新
    */
    #include<iostream>
    #include<stdio.h>
    using namespace std;
    
    #define MAXN 50005
    int ans;
    
    struct node{
        int left,right,sum;
        int mid(){
            return (left+right)>>1;
        }
    }tree[MAXN*4];//注意范围,4倍空间
    
    void btree(int left,int right,int rt){//建树
        tree[rt].left=left;
        tree[rt].right=right;
        if(left==right){
            scanf("%d",&tree[rt].sum);
            return;
        }
        int mid=tree[rt].mid();
        btree(left,mid,rt<<1);
        btree(mid+1,right,rt<<1|1);
        tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;//区间里的点数=左区间+右区间
    }
    
    void query(int left,int right,int rt,int L,int R){//询问求和
        if(L<=left&&right<=R){
            ans+=tree[rt].sum;
            return;
        }
        int mid=tree[rt].mid();
        if(R<=mid)query(left,mid,rt<<1,L,R);//区间在左子树
        else if(L>mid)query(mid+1,right,rt<<1|1,L,R);//区间在右子树
        else{
            query(left,mid,rt<<1,L,R);
            query(mid+1,right,rt<<1|1,L,R);
        }
    }
    
    void update(int left,int right,int rt,int pos,int add){//单点更新函数
        if(left==right){
            tree[rt].sum+=add;
            return;
        }
        int mid=tree[rt].mid();
        if(pos<=mid)update(left,mid,rt<<1,pos,add);//点在左子树
        else update(mid+1,right,rt<<1|1,pos,add);//点在右子树
        tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;//区间和更新
    }
    
    int main(){
        int t,n,a,b,i;
        char str[10];
        scanf("%d",&t);
        for(i=1;i<=t;++i){
            printf("Case %d:
    ",i);
            scanf("%d",&n);
            btree(1,n,1);
            while(~scanf("%s",str)&&str[0]!='E'){
                scanf("%d%d",&a,&b);
                if(str[0]=='A')update(1,n,1,a,b);
                else if(str[0]=='S')update(1,n,1,a,-b);
                else{
                    ans=0;
                    query(1,n,1,a,b);
                    printf("%d
    ",ans);
                }
            }
        }
        return 0;
    }
    View Code

    c2.区间更新

    /*
    线段树
    区间更新
    */
    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    
    #define L(root) ((root)<<1)
    #define R(root) (((root)<<1)|1)
    
    const int MAXN=1024;//
    int numbers[MAXN];//初始值
    
    struct node{
        int left,right;//
        int sum;
        int delta;
        int mid(){
            return left+((right-left)>>1);
        }
    }tree[MAXN*4];//4倍空间
    
    void pushUp(int root){
        tree[root].sum=tree[L(root)].sum+tree[R(root)].sum;
    }
    
    void pushDown(int root){
        if(tree[root].delta){
            tree[L(root)].delta+=tree[root].delta;
            tree[R(root)].delta+=tree[root].delta;
            tree[L(root)].sum+=tree[root].delta*(tree[L(root)].right-tree[L(root)].left+1);
            tree[R(root)].sum+=tree[root].delta*(tree[R(root)].right-tree[R(root)].left+1);
            tree[root].delta=0;
        }
    }
    
    void build(int root,int left,int right){
        tree[root].left=left;
        tree[root].right=right;
        tree[root].delta=0;//不要忘了清空这个
        if(left==right){
            tree[root].sum=numbers[left];
            return;
        }
        int mid=tree[root].mid();
        build(L(root),left,mid);
        build(R(root),mid+1,right);
        pushUp(root);
    }
    
    int query(int root,int left,int right){
        if(tree[root].left==left&&tree[root].right==right){
            return tree[root].sum;
        }
        pushDown(root);
        int mid=tree[root].mid();
        if(right<=mid){
            return query(L(root),left,right);
        }
        else if(left>mid){
            return query(R(root),left,right);
        }
        else{
            return query(L(root),left,mid)+query(R(root),mid+1,right);
        }
    }
    
    void update(int root,int left,int right,int add){
        if(tree[root].left==left&&tree[root].right==right){
            tree[root].delta+=add;
            tree[root].sum+=add*(right-left+1);
            return;
        }
        pushDown(root);
        int mid=tree[root].mid();
        if(right<=mid){
            update(L(root),left,right,add);
        }
        else if(left>mid){
            update(R(root),left,right,add);
        }
        else{
            update(L(root),left,mid,add);
            update(R(root),mid+1,right,add);
        }
        pushUp(root);
    }
    
    int main(){
    
        memset(numbers,0,sizeof(numbers));
    
        int i;
        for(i=1;i<MAXN;++i){
            numbers[i]=i;
        }
    
        build(1,1,10);
    
        cout<<query(1,2,3)<<endl;
    
        update(1,2,3,100);
        cout<<query(1,2,3)<<endl;
    
        return 0;
    }
    View Code

    ps:node节点里面的left和right信息也可以不用保存,在调用函数的时候传下去也可以。

    模板:http://blog.csdn.net/wjw0130/article/details/38498481

  • 相关阅读:
    Android进阶篇系统缓存(一)
    Android提高篇自定义Menu(二)
    Android进阶篇Canvas Bitmap
    Android进阶篇分析伪3D旋转
    Android进阶篇捕获app错误信息
    Android进阶篇Service和广播
    Android进阶篇清除WebView的缓存
    Android进阶篇Parcelable包裹类
    Android进阶篇GestureDetector初探
    Android进阶篇下拉刷新
  • 原文地址:https://www.cnblogs.com/gongpixin/p/5365326.html
Copyright © 2011-2022 走看看