Live2D

[线段树] (a) hdu1166 敌兵布阵单点修改区间求和

(a) hdu1166 敌兵布阵

如在阅读本文时遇到不懂的部分,请在评论区询问,或跳转 线段树总介绍

本题考查区间维护:单点修改、区间求和。

那么显然是线段树,最基础的类型。


 

更新函数

1. 对于一般的单点更新函数,递归地找出点的位置,每次判断在左儿子还是右儿子,最后更新完要回溯pushup。

2. 由于本题是单点修改,也可以采取从下往上修改的方式,即先找到该点,再依次找其父亲直至根节点,每个点pushup,但此时在建树时要记录每个值所对应的点(此点 l==r)。

3. 由于本题是单点修改,也可以把pushup写成 sum[root]+=dalta,因为此区间下一定只有一个点发生改变,故总值也只改变一倍。

4. 区间更新代码(中式英文请见谅)

void update_common(int rt,int x,int delta){
    if(x==t[rt].l&&x==t[rt].r){t[rt].v+=delta;return;}
    if(x<=mid)update_common(ls,x,delta);
    else update_common(rs,x,delta);
    pushup(rt);return;
}
void update_not_common(int x,int delta){
    int rt=pos[x];
    //Attention!Don't write "..+=delta" again for the "pos" node
    while(rt!=1){t[rt].v+=delta;rt>>=1;}
    //Add for the nodes in this road (without pushup)
    return;
}

询问函数

   好普通啊....过水不予讲解

int query(int rt,int x,int y){
    if(x<=t[rt].l&&y>=t[rt].r)return t[rt].v;
    int res=0;
    if(x<=mid)res+=query(ls,x,y);
    if(y>mid)res+=query(rs,x,y);
    return res;
}

总代码

/*hdu1166  两种update均可AC*/

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e7+3;
int T,n,a[N],pos[N];
struct node{int l,r,v;}t[N<<2];
string order;
#define mid (t[rt].l+t[rt].r>>1)
#define ls (rt<<1)
#define rs (ls|1)
#define pushup(rt) t[rt].v=t[ls].v+t[rs].v
void build(int rt,int l,int r){
    t[rt].l=l,t[rt].r=r,t[rt].v=0;
    if(l==r){
        t[rt].v=a[l];
        pos[l]=rt;
        return;}
    build(ls,l,mid);build(rs,mid+1,r);
    pushup(rt);return;
}
void update_common(int rt,int x,int delta){
    if(x==t[rt].l&&x==t[rt].r){t[rt].v+=delta;return;}
    if(x<=mid)update_common(ls,x,delta);
    else update_common(rs,x,delta);
    pushup(rt);return;
}
void update_not_common(int x,int delta){
    int rt=pos[x];
    //Attention!Don't write "..+=delta" again for the "pos" node
    while(rt!=1){t[rt].v+=delta;rt>>=1;}
    //Add for the nodes in this road (without pushup)
    return;
}
int query(int rt,int x,int y){
    if(x<=t[rt].l&&y>=t[rt].r)return t[rt].v;
    int res=0;
    if(x<=mid)res+=query(ls,x,y);
    if(y>mid)res+=query(rs,x,y);
    return res;
}
int main()
{
    //freopen("a.in","r",stdin);
    //freopen("a.out","w",stdout);
    scanf("%d",&T);
    register int x,y,Case=0;
    while(T--){
        printf("Case %d:\n",++Case);
        scanf("%d",&n); //ini();
        for(register int i=1;i<=n;++i)scanf("%d",&a[i]);
        build(1,1,n);
        while(cin>>order&&order!="End"){
            scanf("%d%d",&x,&y);
        if(order=="Add")
            //update_common(1,x,y);
            update_not_common(x,y);
        else if(order=="Sub")
            //update_common(1,x,-y);
            update_not_common(x,-y);
        else
            printf("%d\n",query(1,x,y));
        }    
    }
    return 0;
}

End

posted @ 2019-07-22 17:58  lsy263  阅读(148)  评论(0编辑  收藏  举报