1264. Dynamically find continuous interval sum

Insert picture description here
Insert picture description here
Idea:
Tree-shaped array template
Tree-shaped array code:

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

const int N = 100010;
int n,m;
int s[N],tr[N];

int lowbit(int x)//表示2的x次方
{
    
    
    return x & -x;
}

void add(int x,int v)//某个位置上的数加上一个数
{
    
    
    for(int i = x;i <= n;i += lowbit(i))
    {
    
    
        tr[i] += v;
    }
}

int query(int x)//求某一个的前缀和
{
    
    
    int res = 0;
    for(int i = x;i;i -= lowbit(i))
    {
    
    
        res += tr[i];
    }
    return res;
}

int main()
{
    
    
    int k,a,b;
    scanf("%d %d",&n,&m);
    for(int i = 1;i <= n;i++)
    {
    
    
        scanf("%d",&s[i]);
    }
    for(int i = 1;i <= n;i++)
    {
    
    
        add(i,s[i]);
    }
    while(m--)
    {
    
    
        scanf("%d %d %d",&k,&a,&b);
        if(k == 0)
        {
    
    
            printf("%d\n",query(b) - query(a - 1));
        }
        else
        {
    
    
            add(a,b);
        }
    }
    
    return 0;
}

Idea:
Line segment tree template
line segment tree code:

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

const int N = 100010;
int w[N];
int n,m;
struct node
{
    
    
    int l,r;
    int sum;
}tr[4 * N];
//pushup 求x这个节点的权值=左儿子的权值+右儿子的权值
void pushup(int u)
{
    
    
    tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}
//建立l ~ r 的线段树
void build(int u,int l,int r)
{
    
    
   //如果l==r 说明这个区间已经不能再分(长度为1)
   //直接给它赋值
   if(l == r) 
   tr[u] = {
    
    l,r,w[r]};
   else
   {
    
    
        //不是叶子节点 先给他的l r 当前l
        tr[u] = {
    
    l,r};
        int mid = l + r >> 1;
        //递归分出 左边 右边
        build(u << 1,l,mid);
        build(u << 1 | 1,mid + 1,r);
        //递归结束后回溯算出 每个父亲的区间和
        pushup(u);
   }
}
//查询函数 给定根节点 查询l~r这个子区间的和
int query(int u,int l,int r)
{
    
    
     //如果序列完全包含这个子区间 则直接加上
   if(tr[u].l >= l && tr[u].r <= r) return tr[u].sum;
   int mid = tr[u].l + tr[u].r >> 1;
   int sum = 0;
    //不完全包含则递归找下去
    //如果和左儿子有关联 递归左边
   if(l <= mid) sum += query(u << 1,l,r);
    //如果和右儿子有关系 递归右边
   if(r > mid) sum += query(u << 1 | 1,l,r);
   return sum;
}
//修改操作
void modify(int u,int x,int v)
{
    
    
    //如果他是一个叶子节点
    //则直接加上这个值
    if(tr[u].l == tr[u].r) tr[u].sum += v;
    else
    {
    
    
        int mid = tr[u].l + tr[u].r >> 1;
        //如果这个数的位置在他的左边
        //递归修改他的左儿子等
        if(x <= mid) modify(u << 1,x,v);
        //如果这个数的位置在他的右边
        //递归修改他的右儿子等等
        else modify(u << 1 | 1,x,v);
        pushup(u);
    }
}

int main()
{
    
    
    scanf("%d %d",&n,&m);
    for(int i = 1;i <= n;i++)
    {
    
    
        scanf("%d",&w[i]);
    }
    build(1,1,n);
    int k,a,b;
    while(m--)
    {
    
    
        scanf("%d %d %d",&k,&a,&b);
        if(k == 0) printf("%d\n",query(1,a,b));
        else modify(1,a,b);
    }
    
    
    return 0;
}

Guess you like

Origin blog.csdn.net/qq_45812180/article/details/114791306