• [线段树] (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:
    ",++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
    ",query(1,x,y));
            }    
        }
        return 0;
    }

    End

  • 相关阅读:
    Java开发笔记(四十二)日历工具的常见应用
    Java开发笔记(四十一)日历工具Calendar
    Java开发笔记(四十)日期与字符串的互相转换
    Java开发笔记(三十九)日期工具Date
    Java开发笔记(三十八)利用正则表达式校验字符串
    Java开发笔记(三十七)利用正则串分割字符串
    Java开发笔记(三十六)字符串的常用方法
    Java开发笔记(三十五)字符串格式化
    Git 工作流程
    如果你恨一个程序员,忽悠他去做iOS开发
  • 原文地址:https://www.cnblogs.com/lsy263/p/11227428.html
Copyright © 2020-2023  润新知