hdu 1166 敌兵布阵 (单点更新线段树模板)

版权声明:转载注明下出处就行了。 https://blog.csdn.net/LJD201724114126/article/details/84729117

题目链接:哆啦A梦传送门

题解:

参考链接:https://www.cnblogs.com/TenosDoIt/p/3453089.html

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

const int maxn=50010;

struct node{
    int val;
}segtree[maxn*4];

int arr[maxn];

/*
 root:当前线段树的根节点下标
 arr: 用来构造线段树的数组
 istart:数组的起始位置
 iend:数组的结束位置
 */
void build(int root,int istart,int iend)
{
    if(istart==iend){ ///叶子节点
        segtree[root].val=arr[istart];
    }
    else{

        int mid=(istart+iend)/2;
        build(root*2,istart,mid); ///递归构造左子树
        build(root*2+1,mid+1,iend);///递归构造右子树

         ///根据左右子树根节点的值,更新当前根节点的值
        segtree[root].val=segtree[root*2].val+segtree[root*2+1].val;

    }
}
/*
功能:线段树的区间查询
root:当前线段树的根节点下标
[nstart, nend]: 当前节点所表示的区间
[qstart, qend]: 此次查询的区间
*/
int query(int root,int nstart,int nend,int qstart,int qend)
{
    ///查询区间和当前节点区间没有交集
    if(qstart>nend||qend<nstart)
        return 0;

        ///当前节点区间包含在查询区间内
    if(qstart<=nstart&&qend>=nend)
        return segtree[root].val;

        ///分别从左右子树查询,返回两者查询结果的较小值
    int mid=(nstart+nend)/2;

    return query(root*2,nstart,mid,qstart,qend)
    +query(root*2+1,mid+1,nend,qstart,qend);
}

/*
功能:更新线段树中某个叶子节点的值
root:当前线段树的根节点下标
[nstart, nend]: 当前节点所表示的区间
index: 待更新节点在原始数组arr中的下标
addVal: 更新的值(原来的值加上addVal)
*/
void updataone(int root,int nstart,int nend,int index,int addval)
{
    if(nstart==nend)
    {
        if(index==nstart) ///找到了相应的节点,更新之
        {
             segtree[root].val+=addval;
             return;
        }

    }
    int mid=(nstart+nend)/2;

    if(index<=mid) ///在左子树中更新
        updataone(root*2,nstart,mid,index,addval);
    else
        updataone(root*2+1,mid+1,nend,index,addval);///在右子树中更新

        ///根据左右子树的值回溯更新当前节点的值
    segtree[root].val=segtree[root*2].val+segtree[root*2+1].val;

}
char str[10];
int main()
{

    int ncase,n,x,y;

    scanf("%d",&ncase);
    int T=0;

    while(ncase--)
    {
        scanf("%d",&n);

        for(int i=1;i<=n;i++)
            scanf("%d",&arr[i]);
        build(1,1,n);

        printf("Case %d:\n",++T);
        while(scanf("%s",str))
        {

            if(strcmp(str,"End")==0) break;
            else if(strcmp(str,"Query")==0)
            {
                scanf("%d%d",&x,&y);
                printf("%d\n",query(1,1,n,x,y));
            }
            else if(strcmp(str,"Add")==0)
            {
                scanf("%d%d",&x,&y);
                updataone(1,1,n,x,y);
            }
            else if(strcmp(str,"Sub")==0)
            {
                scanf("%d%d",&x,&y);
                updataone(1,1,n,x,-y);
            }
        }

    }
    return 0;
}

参考神犇kuangbin模板,

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

const int maxn=50010;

struct node{
    int l,r;
    int val;
}segtree[maxn*4]; ///每个节点表示的范围 值

int arr[maxn];

void build(int root,int istart,int iend) ///建树
{

    segtree[root].l=istart;///存储此节点的左右范围
    segtree[root].r=iend;
    if(istart==iend){
        segtree[root].val=arr[istart];
    }
    else{

        int mid=(istart+iend)>>1;
        build(root<<1,istart,mid);
        build(root<<1|1,mid+1,iend);
        segtree[root].val=segtree[root<<1].val+segtree[root<<1|1].val;

    }
}

int query(int root,int qstart,int qend)
{

    if(qstart==segtree[root].l&&qend==segtree[root].r) ///此节点恰好满足
        return segtree[root].val;

    int mid=(segtree[root].l+segtree[root].r)>>1;


    if(qend<=mid) return query(root<<1,qstart,qend); ///在左子树
    else if(qstart>mid) return query(root<<1|1,qstart,qend); ///在右子树


    return query(root<<1,qstart,mid)+query(root<<1|1,mid+1,qend);
}

void updataone(int root,int index,int addval) ///在位置index加上值addval
{
    ///在此节点加上
    segtree[root].val+=addval;
    if(segtree[root].l==index&&segtree[root].r==index) return;

    int mid=(segtree[root].l+segtree[root].r)>>1;

    if(index<=mid) ///在左子树
        updataone(root<<1,index,addval);
    else
        updataone(root<<1|1,index,addval);


}
char str[10];
int main()
{

    int ncase,n,x,y;

    scanf("%d",&ncase);
    int T=0;

    while(ncase--)
    {
        scanf("%d",&n);

        for(int i=1;i<=n;i++)
            scanf("%d",&arr[i]);
        build(1,1,n);

        printf("Case %d:\n",++T);
        while(scanf("%s",str))
        {

            if(strcmp(str,"End")==0) break;
            else if(strcmp(str,"Query")==0)
            {
                scanf("%d%d",&x,&y);
                printf("%d\n",query(1,x,y));
            }
            else if(strcmp(str,"Add")==0)
            {
                scanf("%d%d",&x,&y);
                updataone(1,x,y);
            }
            else if(strcmp(str,"Sub")==0)
            {
                scanf("%d%d",&x,&y);
                updataone(1,x,-y);
            }
        }

    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/LJD201724114126/article/details/84729117