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;
}