數列操作 資訊學奧賽一本通--T1535(樹狀陣列)
阿新 • • 發佈:2021-01-22
【題目描述】
給定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;
}