【题目描述】
给定n个数列,规定有两种操作,一是修改某个元素,二是求子数列[a,b]的连续和。数列元素个数最多10万个,询问操作最多10万次。【输入】
第一行2个整数n,m(n表示输入n个数,m表示m操作)
第二行n个整数
接下来m行,每行三个数k,a,b(k=0,表示求子数列[a,b]的连续和;k=1,表示第a个数加b)。【输出】
若干行,表示k=0时,对应子数列[a,b]连续和。【输入样例】
10 5
1 2 3 4 5 6 7 8 9 10
1 1 5
0 1 3
0 4 8
1 7 5
0 4 8
【输出样例】
11
30
35
这个题刚开始看感觉好简单,就直接写,结果没有通过,超时了
后来在网上查了查解题需要用到树状数组,这个树状数组我觉得如果理解了写题就很方便,并且树状数组可以实现区间查询和单点修改,并且对于这个题里的要求
数列元素个数最多10万个,询问操作最多10万次。
可以高效实现,注意这个题需要大量输入和输出所以要使用scanf和printf函数输入和输出。
我在网上看的树状数组是通过这个博客写的很清楚明白,并且把树状数组介绍的很清楚。我还得再写几个题好好练练,再好好理解理解。
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define maxn 100100
int c[maxn];
int n,m;
int lowbit(int x){
return x&(-x);}
void update(int a,int b)
{
for(int i=a;i<=n;i=i+lowbit(i))
c[i]+=b;
}
int isum(int a)
{
int nsum=0;
for(int i=a;i>0;i=i-lowbit(i))
nsum+=c[i];
return nsum;
}
int main()
{
memset(c,0,sizeof(c));
int x;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
update(i,x);
}
int k,a,b;
while(m--)
{
scanf("%d%d%d",&k,&a,&b);
if(k==1)
update(a,b);
else
printf("%d\n",isum(b)-isum(a-1));
}
return 0;
}