树状数组(单点修改,区间询问)

来源:互联网 发布:淘宝商品图片下载 编辑:程序博客网 时间:2024/05/16 09:59


题目描述

输入一个数列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));//初始为0memset(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;}


0 0
原创粉丝点击