假设要在连续的一段区域[l,r]内都加上n,用暴力方法要执行r-l+1次
如果有这么一道题:有100000个数初始都为0,有100000次执行操作,每次操作输入三个数l,r,x代表区间[l,r]的数上都加上x,要输出最后的数列
如果用循环遍历的方法执行每一次操作,可能要执行100000*100000次,肯定会T掉,这时就要用到前缀和了。
[l,r]都加上x ,我们假设一个数组sum[100000],sum[i]代表sum数组的前面1–i的和,如果sum[7]=5,(sum初始都为0),那么s[8],sum[9],sum[10]…都为5了,这里只要执行一次就可以了
因此解决上面的问题,只需要sum[l]+=x,sum[r+1]-=x;维护一个前缀和就行了。
看看实际题目
很直观,被覆盖就在这个覆盖区域上+1,如果用暴力遍历每一个操作又会超时,那对于每一行,只需记录两个数x1,x2 在[x1,x2]里面都加上1,sum[x1]++,sum[x2+1]–;维护就可以了。简单题目不在累赘
下面进阶:
这题需要一点树状数组的知识,假设我们已经会了。。
这题是洛谷的2184, 看看数据,知道地雷最多有100000种,那么我们可以用一个前缀和来维护,开始区域用1,结束的时候用一个足够大的数表示这里已经结束了,结果就除去这个大数得到的余数就是之前出现过的种类了。
列如[5,9],在[5,9]上埋下第一种雷,那么sum[5]++,sum[10]+=100007,
[1,7]在[1,7]上埋下第二种雷,sum[1]++,sum[8]+=100007,
最后我们们能算出r之前出现的地雷种类数,l之前出现的种类数,相减就可以得出答案
AC代码:
#include<iostream>
#define ll long long
#define p 100007
using namespace std;
ll sum[100005<<2];
ll n;
ll lowbit(ll x