线段树

来源:互联网 发布:linux 监控java进程 编辑:程序博客网 时间:2024/06/13 05:03

NYIST 士兵杀敌(二)

 
#include<stdio.h>
#include<string.h>
int a[1000005];
struct Tree
{
    int left,right;//左右节点
    int sum;
};
struct Tree tree[2100000];//这种写法树的枝叶可能太多所以tree【】要申请的大一点
// 不能和a数组一样大 他的空间复杂度小于4*a数组应该开为a数组的四倍
void build(int id,int l,int r)
{
    //printf("~~~%d %d %d\n",id,l,r);
    tree[id].left=l;
    tree[id].right=r;
    if(l==r)
    {
        tree[id].sum=a[l];
        return ;
    }
    else
    {
        int mid=(l+r)/2;
        build(id*2,l,mid);//递归建立左节点
        build(id*2+1,mid+1,r);//递归建立右节点
        tree[id].sum=tree[id*2].sum+tree[id*2+1].sum;//根节点的sum存放的是两个节点的总和
    }
}
void update(int id,int pos,int val)
{
    if(tree[id].left==tree[id].right)//当左右节点相同时,左右节点也等于pos即更新的节点
    {
        tree[id].sum+=val;
        return ;
    }
    else
    {
        int mid=(tree[id].left+tree[id].right)/2;
        if(pos<=mid)
            update(id*2,pos,val);
        else
            update(id*2+1,pos,val);
        tree[id].sum=tree[id*2].sum+tree[id*2+1].sum;
    }
}
int q(int id,int l,int r)
{
    if(tree[id].left==l&&tree[id].right==r)
        return tree[id].sum;
    else
    {
        int mid=(tree[id].left+tree[id].right)/2;
        if(l>mid)
            return q(id*2+1,l,r);
        else if(r<=mid)
            q(id*2,l,r);
        else
            return q(id*2,l,mid)+q(id*2+1,mid+1,r);
    }
}
int main()
{
    int i,n,m,b,c;
    char str[50];
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)
       scanf("%d",&a[i]);
    build(1,1,n);
    while(m--)
    {
        scanf("%s",str);
        if(strcmp("QUERY",str)==0)
        {
            scanf("%d%d",&b,&c);
            printf("%d\n",q(1,b,c));
        }
        if(strcmp("ADD",str)==0)
        {
            scanf("%d%d",&b,&c);
            update(1,b,c);
        }
    }
    return 0;
}


       
0 0
原创粉丝点击