今天给大家分享一下树状数组。
题目:
给出一个有n个元素的整数数组A,(1<=n<=100000) 有m(1<=m<=100000)个命令,这些命令有两种形式:(1) C i j,表示将元素a[i]的值修改为整数j (2) Q i,表示求前缀和Si=A1+A2+…+Ai的值。
输入格式:
包含m+2行: 第1行有二个整数n和m,以一个空格分隔。 第2行有n个整数,互相以空格分隔,表示初始时数组中的n个元素的值。 第3行开始至第m+2行中,第j+2行表示第j个命令 如果该行的第1个字符为大写字母C,则C后会有两个整数,每个整数前会有一个空格。 如果该行的第1个字符为大写字母Q,则Q后会有一个整数i,该整数前会有一个空格。
输出格式:只有一行,该行有若干个整数,每个整数表示要求输出的一个前缀和。 每个输出的前缀和之间互相以一个空格分隔,前后不能有多余空格。
输入样例:
3 2 1 2 3 C 1 10 Q 3
输出样例:
15
代码样例:
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m);
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define REP(i,N) for(int i=0;i<(N);i++)
#define CLR(A,v) memset(A,v,sizeof A)
using namespace std;
#pragma GCC optimize (3)
int n,m,us;
ll intm[100009],intn[100009];
void modify(int x,ll dx)
{
intn[x]+=dx;
intm[(x-1)/us+1]+=dx;
}
int query(int x)
{
ll sum=0;
for(int i=1;i<=(x-1)/us;i++)
{
sum+=intm[i];
}
for(int i=(x-1)/us*us+1;i<=x;i++)
{
sum+=intn[i];
}
return sum;
}
int main()
{
scanf("%d%d",&n,&m);
us=sqrt(n);
for(int i=1;i<=n;i++)
{
scanf("%d",&intn[i]);
intm[(i-1)/us+1]+=intn[i];
}
char k[2];
int x,y;
for(int i=1;i<=m;i++)
{
scanf("%s",k);
if(k[0]=='C')
{
scanf("%d%d",&x,&y);
modify(x,y-intn[x]);
}
else if(k[0]=='Q')
{
scanf("%d",&x);
ll sum=query(x);
printf("%lld\n",sum);
}
}
return 0;
}//代码仅供参考,请勿转载。
//wangmy
392

被折叠的 条评论
为什么被折叠?



