时间戳优化树状数组的频繁清空
来自@zx2017老师的ppt Orz
适用场景:
给定 $T$ 组数据,每组数据有 $Q$ 个询问,询问给定 $n$ 个数的区间和
数据范围:$T\le 2\times 10^5,~\sum Q \le 2\times 10^5,~n\le 5\times 10^5$
注意,这里只限制了 $\sum Q$ ,并没有限制 $\sum n$
对于每组数据不能直接去清空数组,因为 $T \times n$ 肯定爆炸
考虑维护一个时间戳now
,也就是现在是第几组数据
对于是这组数据的,也就是t[i]==now
的情况,直接用
如果不是这组数据的,我们要先清零,再加。
注意到 tree[i]=0,tree[i]+=v
其实等价于 tree[i]=v
由于我们只有查询到一个树上结点,才会去判断它的时间戳
因此这类题目的时间复杂度可以控制在 $O(\sum Q \log \sum Q)$
修改部分的代码:
int tree[N],t[N],now=0;
void add(int x,int v)
{
for(int i=x; i<=n; i+=lowbit(i))
if(t[i]==now)tree[i]+=v;
else t[i]=now,tree[i]=v; // tree[i] = 0 + v
}
int sum(int x)
{
int res=0;
for(int i=x; i; i-=lowbit(i))
if(t[i]==now) res+=tree[i];
else t[i]=now,tree[i]=0; // res+=0
return res;
}
然后我感觉这个东西是可以搞到线段树上的
具体的,维护每个树上结点的时间戳 t[N<<2]
这样可能可以维护更多的区间性质
问了一下老师,确实可以这么去搞
代码还没写,目前没找到类似思想的题目,但是这个技巧挺有趣的。
upd.20220722 P1120 小木棍 ,清空临时标记数组vis,类似于这个优化
这么一说,好像匈牙利算法也是可以这么优化的来着。。。