线段树

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:\n",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\n",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

 

posted @ 2016-04-07 20:35  gongpixin  阅读(247)  评论(0编辑  收藏  举报