題目描述
如題,已知一個數列,你需要進行下面兩種操作:
1.將某區間每一個數數加上x
2.求出某一個數的值
輸入格式
第一行包含兩個整數N、M,分別表示該數列數字的個數和操作的總個數。
第二行包含N個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。
接下來M行每行包含2或4個整數,表示一個操作,具體如下:
操作1: 格式:1 x y k 含義:將區間[x,y]內每個數加上k
操作2: 格式:2 x 含義:輸出第x個數的值
輸出格式
輸出包含若干行整數,即爲所有操作2的結果。
輸入輸出樣例
輸入 #1複製
5 5 1 5 4 2 3 1 2 4 2 2 3 1 1 5 -1 1 3 5 7 2 4
輸出 #1複製
6 10
說明/提示
時空限制:1000ms,128M
數據規模:
對於30%的數據:N<=8,M<=10
對於70%的數據:N<=10000,M<=10000
對於100%的數據:N<=500000,M<=500000
樣例說明:
故輸出結果爲6、10
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
const int maxn = 5e6+5;
int n,m,tree[maxn];
int lowber(int x)
{
return x & -x;
}
void add(int x,int k)
{
while(x<=n)
{
tree[x]+=k;
x += lowber(x);
}
}//讓x點加k單點更改
int sum(int x)
{
int ans= 0;
while(x)
{
ans+=tree[x];
x-=lowber(x);
}
return ans;
}//查詢x的前綴和
void addlr(int l,int r,int sum)
{
add(l,sum);
add(r+1,-sum);
}//區間加
int main()
{
scanf("%d%d",&n,&m);int v = 0;
for(register int i = 1;i <= n;++i)
{
int a;
scanf("%d",&a);
add(i,a-v);//加入樹狀數組要add加
v = a;//和單點修改和區間查詢的不同這裏要變
}
int u;
int flag,x,y,sum1;
while(m--)
{
scanf("%d",&flag);
if(flag == 1)
{
scanf("%d%d%d",&x,&y,&sum1);
addlr(x,y,sum1);
}
else{
scanf("%d",&x);
printf("%d\n",sum(x));
}
}
return 0;
}