HDU 1166 敌兵布阵 线段树入门_单点更新

线段树是连续区间动态更新的有力工具,由二叉树的特性可知其操作复杂度为 log(N)

本题是最最基础的线段树,但由此也算是入门了

线段树学习推荐优秀博客:点击打开链接


/* ***********************************************
Author        :angon
Created Time  :2016/3/27 20:00:05
File Name     :
************************************************ */

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
const int maxn=50005;
int a[maxn];
struct node
{
  int left,right;
  int value;
};
node segTree[4*maxn];

void build(int i,int l,int r)
{
    segTree[i].left=l;
    segTree[i].right=r;
    if(l==r)
    {
        segTree[i].value=a[l];
        return ;
    }
    //递归构造左右子树
    build(i<<1,l,(l+r)>>1);  
    build(i<<1|1,((l+r)>>1)+1,r);    // |1相当于+1
    segTree[i].value=segTree[i<<1].value+segTree[i<<1|1].value;  //回溯时更新节点信息(由下至上)
}
void add(int i,int x,int y)  //单点更新信息,将y加到a[x]上,并更新被其影响的节点的值
{
    if(segTree[i].left==segTree[i].right && segTree[i].left==x)  //找到所更新的节点
    {
        segTree[i].value+=y;
        return ;
    }
    int mid=(segTree[i].left+segTree[i].right)>>1;
    if(x<=mid) add(i<<1,x,y);
    else       add(i<<1|1,x,y);
    segTree[i].value=segTree[i<<1].value + segTree[i<<1|1].value; //回溯时更新节点信息
}

int ans;
void query(int i,int l,int r)  //查询信息,l,r为所有查询的区间
{
    if(segTree[i].left==l && segTree[i].right==r)  //找到一次完全重合的区间
    {
        ans+=segTree[i].value;
        return ;
    }
     //递归齐左右孩子
    i<<=1;     
    if(l<=segTree[i].right)     //如果区间涉及左孩子,递归左孩子,下同
        query(i,l,min(segTree[i].right,r));
    i++;
    if(r>=segTree[i].left)
        query(i,max(l,segTree[i].left),r);

}

int main()
{
    int T,n,ca=0;
    scanf("%d",&T);
    while(T--)
    {
        printf("Case %d:\n",++ca);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        build(1,1,n);
        char s[6];
        while(scanf("%s",s))
        {
            if(s[0]=='E') break;
            int x,y;
            scanf("%d%d",&x,&y);
            if(s[0]=='A')
                add(1,x,y);
            else if(s[0]=='S')
                add(1,x,-y);
            else if(s[0]=='Q')
            {
                ans=0;
                query(1,x,y);
                printf("%d\n",ans);
            }
        }
    }


    return 0;
}


你可能感兴趣的:(HDU 1166 敌兵布阵 线段树入门_单点更新)