数列操作 信息学奥赛一本通--T1535(树状数组)

原题链接

【题目描述】
给定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;
}

猜你喜欢

转载自blog.csdn.net/Huo6666/article/details/112969713
今日推荐