【模板】樹狀數組 2 區間加法加上單點查詢

題目描述

如題,已知一個數列,你需要進行下面兩種操作:

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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章