P3368 【模板】树状数组 2

29 阅读2分钟

P3368 【模板】树状数组 2

这道题目是差分数组与树状数组的结合,这题每次改变并且查询的是a数组,但是如果直接改变a数组又难免会出现每次都要重新进行前缀和等一系列操作,所以要思考如何将对段的修改变成对单个点的修改和查询,这就可以想到差分了。

例如原始数组是a,再新建一个数组b,使b[i] = a[i] - a[i - 1],如此一来就可以令a[i] = b[1] + b[2] + b[3] +........+ b[i],如此一来,假如要使a数组[l , r]区间内的元素急加上cnt,就只需要让b[l] += cnt,b[r + 1] -= cnt,如此一来就只需要修改单个点即可完成对a的改变,出现对单个点的修改与维护以及前缀和就会想到树状数组。

树状数组的add函数与query函数与树状数组1中的别无二致,这里就主要看一下主函数的变化。



   	ll last = 0;
   	for(int i = 1 ; i <= n ; i++)
   	{
   		int num;
   		cin>>num;
   		add(i , num - last);
   		last = num;
	}
    

这里是读入a数组生成b数组。


	while(m--)
	{
		int flag;
		cin>>flag;
		if(flag == 1)
		{
			int x,y,k;
			cin>>x>>y>>k;
			add(x , k);
			add(y + 1 ,-k);
		}else
		{
			int x;
			cin>>x;
			cout<<query(x)<<"\n";
		} 
	}
    

这里的1操作是对a数组在区间[x , y]之间加上k,和正常的差分一样的思路,2操作则是输出第x个数的值,这里的query就是实现了a[i] = b[1] + b[2] + b[3] +........+ b[i]的操作,从顶层往下加即可。

最后是AC代码:

//#pragma GCC optimize(1)
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
//#pragma GCC optimize("Os")
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("Og")
//#pragma GCC optimize("inline")
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair <ll , ll> pii;
typedef priority_queue <ll ,vector<ll> ,greater<ll> > xiao;  
typedef priority_queue <ll ,vector<ll> ,less<ll> > da; 
const int N=5e5 + 10,M = 0x3f3f3f3f;
const ull P = 131;

int n,m;
int c[N];

ll lowbit(int x)
{
    return x&(-x);
}

void add(int u,int cnt)
{
	for(int i = u ; i <= n ; i += lowbit(i))
	{
		c[i] += cnt;
	}
}

int query(int k)
{
	int ans = 0;
	for(int i = k ; i >= 1 ; i -= lowbit(i))
	{
		ans += c[i];
	}
	
	return ans;
}

int main()
{
	std::ios::sync_with_stdio(false);
    std::cin.tie(0),cout.tie(0);
    
   	cin>>n>>m;
   	ll last = 0;
   	for(int i = 1 ; i <= n ; i++)
   	{
   		int num;
   		cin>>num;
   		add(i , num - last);
   		last = num;
	}
	
	while(m--)
	{
		int flag;
		cin>>flag;
		if(flag == 1)
		{
			int x,y,k;
			cin>>x>>y>>k;
			add(x , k);
			add(y + 1 ,-k);
		}else
		{
			int x;
			cin>>x;
			cout<<query(x)<<"\n";
		} 
	}
}