题目描述
输入一个数列A1,A2….An(1<= N <=100000),在数列上进行M(1<=M <=100000)次操作,操作有以下两种:
(1)格式为C I X,其中C为字符“C”,I和X(1<= I<= N, |X| <=10000)都是整数,表示把把a[I]改为X
(2)格式为Q L R,其中Q为字符“Q”,L和R表示询问区间为[L,R](1<= L <= R <= N),表示询问A[L]+…+A[R]的值。
输入格式 1319.in
第一行输入N(1<= N <=100000),表述数列的长度,接下来N行,每行一个整数(绝对值不超过10000)依次输入每个数;接下来输入一个整数M(1<= M <=100000),表示操作数量,接下来M行,每行为C I X或者Q L R。
输出格式 1319.out
对于每个Q L R 的操作输出答案。
输入样例 1319.in
5
1
2
3
4
5
3
Q 2 3
C 3 9
Q 1 4
输出样例 1319.out
5
16
【解题思路】
单点修改时向上修改,区间询问时向前询问。要求区间[x,y]之间的和,就求sum(y)-sum(x-1)的值。至于树状数组针对的是加上某值,而题意中说的“改为某值”,则操作时加上的是(要改的值-原本的值)。
【AC代码】
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=100010;
int n,m;
int a[maxn];
int c[maxn];
char s[2];
int lowbit(int p)
{
return (p&(-p));
}
void add(int p,int num)
{
while (p<=n)
{
c[p]+=num;
p+=lowbit(p);//向上修改
}
return;
}
int query(int p)
{
int tmp=0;
while (p)
{
tmp+=c[p];
p-=lowbit(p);//向前询问
}
return tmp;
}
int main()
{
freopen("1319.in","r",stdin);
freopen("1319.out","w",stdout);
scanf("%d",&n);
memset(a,0,sizeof(a));//初始为0
memset(c,0,sizeof(c));
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
add(i,a[i]);//加上a[i]
}
scanf("%d",&m);
for (int i=1;i<=m;i++)
{
scanf("%s",s);
if (s[0]=='C')
{
int j,k;
scanf("%d%d",&j,&k);
add(j,k-a[j]);// 加上的是(要改的值-原本的值)。
a[j]=k;//更新原数组的值
}else
{
int l,r;
scanf("%d%d",&l,&r);
int sum=query(r)-query(l-1);//区间求和
printf("%d\n",sum);
}
}
return 0;
}