【单点更新,区间查询,线段树】【HDU1166】【敌兵布阵】

线段树要捡回来学了


才知道以前抄的模板就是杭电传奇学长写的,写起来更有激情了;


一点注意:

单点更新完后记得pushup(),向上更新信息

以下是对线段树的理解

线段树的节点代表一段线段,节点编号没有任何意义。

叶子节点代表点,一般也代表具体的数值了,是线段树的主要注意部分;


#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#define oo 0x13131313
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn=55555;
using namespace std;
int N;
int tree[maxn*4];
void init()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
}
void pushup(int rt)
{
    tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
int build(int l,int r,int rt)
{
    if(l==r) {scanf("%d",&tree[rt]);return 0;}
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    pushup(rt);
}
int updata(int p,int k,int l,int r,int rt)//单点更新
{
    int m;
    if(l==r) {tree[rt]+=k;return 0;}
    m=(l+r)>>1;
    if(p<=m) updata(p,k,lson);
    else updata(p,k,rson);
    pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
    int temp=0,m;
    if(L<=l&&r<=R) return tree[rt];
    m=(l+r)>>1;
    if(L<=m) temp=temp+query(L,R,lson);
    if(R>m)  temp=temp+query(L,R,rson);
    return temp;
}
char buffer[10];
int main()
{
    int CASE=0;
   // init();
    int T;
    cin>>T;
    while(T--)
    {
        int a,b;
        CASE++;
        cin>>N;
        build(1,N,1);
        printf("Case %d:
",CASE);
                while(scanf("%s",buffer))
                {
                    if(buffer[0]=='E') break;
                    scanf("%d%d",&a,&b);
                    if(buffer[0]=='A') updata(a,b,1,N,1);
                    else if(buffer[0]=='S') updata(a,-b,1,N,1);
                    else if(buffer[0]=='Q') printf("%d
",query(a,b,1,N,1));
                }
        }
}


原文地址:https://www.cnblogs.com/zy691357966/p/5480383.html