线段树(单点操作)

单点操作
//元素
struct node {
    int l, r, sum;
} tr[maxn<<2]; //节点类型
//建树
void pushup(int m) { //向上更新
    tr[m].sum=tr[m<<1].sum+tr[m<<1|1].sum;//一个节点的sum等于左节点的sum加右节点的sum
}
void build(int m, int l, int r) { //建树
    tr[m].l=l;       //最左
    tr[m].r=r;      //最右
    if(l==r) {      //只有一个点l==r
        scanf("%d", &tr[m].sum);
        return;
    }    //直接结束
    int mid=(l+r)>>1;//求中间值
    build(m<<1, l, mid);//左半边  m*2
    build(m<<1|1, mid+1, r);//右半边  m*2+1
    pushup(m);//向上更新
}
//单点更新
void updata(int m, int inx, int val) {
    if(tr[m].l==inx&&tr[m].r==inx) { //如果找到那个值,直接更新
        tr[m].sum+=val;
        return;
    }
    int mid=(tr[m].l+tr[m].r)>>1;//求中间值
    if(inx<=mid)    //如果要找的值小于中间值,更新左半边
        updata(m<<1, inx, val);
    else
        updata(m<<1|1, inx, val);//更新右半边
    pushup(m);//向上更新
}
//查询
int query(int m, int l, int r) {//查询l到r
    if(tr[m].l==l&&tr[m].r==r) {//如果找到那个区域,输出和(可以换)
        return tr[m].sum;
    }
    int mid=(tr[m].l+tr[m].r)>>1;//求中间值
    int temp;
    if(r<=mid)//若中间值在要找区域的右边
        temp=query(m<<1, l ,r);//查询左半部分
    else if(l>mid)
        temp=query(m<<1|1, l, r);
    else//若mid 在所要找到范围里
        temp=query(m<<1, l, mid)+query(m<<1|1, mid+1, r);//查询(l,mid)和(mid,r)
    return temp;
}

 


版权声明:本文为red_red_red原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。