差分化樹狀數組(模板題)

normal版本的樹狀數組模板可完成兩種操作(單次都是O(logn)):
①單點修改②區間求和
那麼如果題目變成了基礎線段樹的要求:
①區間修改②單點詢問
事實上樹狀數組也是可以優雅地解決這個問題的,而且代碼量的確低得驚人
這需要我們注意到一個無腦而有趣的等式
an=1n(aiai1)a_{n}=\sum_{1}^{n}(a_{i}-a_{i-1})(不妨讓a0=0a_{0}=0
這種操作有個看似高貴的名字——差分
那麼提示至此,相信讀者也能很快地想出該題的做法了

讀入時差分存儲bi=aiai1b_{i}=a_{i}-a_{i-1},詢問時用bnb_{n}的前i項和代表aia_{i},修改時增加blb_{l}的值,減少br+1b_{r+1}的值

附上洛谷原題

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

1.將某區間每一個數數加上x

2.求出某一個數的值

輸入輸出格式 輸入格式: 第一行包含兩個整數N、M,分別表示該數列數字的個數和操作的總個數。

第二行包含N個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。

接下來M行每行包含2或4個整數,表示一個操作,具體如下:

操作1: 格式:1 x y k 含義:將區間[x,y]內每個數加上k

操作2: 格式:2 x 含義:輸出第x個數的值

輸出格式: 輸出包含若干行整數,即爲所有操作2的結果。

https://www.luogu.org/problemnew/show/P3368

AC代碼:

#include <bits/stdc++.h>
using namespace std;
const int MAXN=5e5+10;
int n,m,k,x,y,z,a[MAXN],tree[MAXN];

int lowbit(int x)     //get the lowest "1" in x(binary form)    eg. lowbit(1100(2))=100(2)=4
{
	return x & -x;
}

void update(int i,int x)
{
	for (;i<=n;tree[i]+=x, i+=lowbit(i));
}

long long sum(int i)
{
	long long ret=0;
	for (;i;ret+=tree[i], i-=lowbit(i));
	return ret;
}

int main()
{
	cin>>n>>m;
	a[0]=0;
	for (int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		update(i,a[i]-a[i-1]);
	}
	for (int i=1;i<=m;i++)
	{
		scanf("%d%d",&k,&x);
		if (k-1) printf("%lld\n",sum(x));
		else 
		{
			scanf("%d%d",&y,&z);
			update(x,z);
			update(y+1,-z);
		}
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章