这一篇博客将教你什么?

如何用LCT打延迟标记,LCT和线段树延迟标记间的关系,为什么延迟标记要这样打。

——正片开始——

学习这一篇博客前,确保你会以下知识:

Link-Cut-Tree,普通线段树

当然,不会也没有关系,你可以先收藏这篇博客,等你学了以后再来看。

 

最好通过了这一道题:【模板】线段树Ⅱ

没有通过也没关系,对于本篇的知识只是一个启发作用。

我们平时使用的Link-Cut-Tree一般只需要打一个翻转标记rev[x]。

然后我们用pushR(x)函数来下发翻转标记。

那么我们现在来看这样一道题:TreeⅡ

练习LCT打标记的绝世好题,可以说就是一道模板题了。

我们来看它需要维护什么:树的权值。

如果能把这个操作2去掉,树剖将绝杀,可惜换不得。

单走一个“树”,nice,直接LCT。

询问权值和,可以,给LCT来一个下传标记,开始你的操作秀。

我们直接来看pushdown部分:

操作有乘和加两种,根据运算法则,乘法优先,所以首先判断

if(lazM[x]!=1){...}

然后是加法

if(lazA[x]){...}

最后回到我们的翻转标记。

然后我们来看pushM和pushA部分

复制代码
#define mul(x,y) x*=y;x%=MOD; inline void pushM(unsigned int x,unsigned int d){     mul(sum[x],d);mul(val[x],d);//节点信息直接更新    mul(lazM[x],d);mul(lazA[x],d);//按照运算法则先把乘标记乘了,再把加标记乘了}
复制代码

有没有回想起什么?没错,就是线段树的懒标记。

我们看看线段树2的懒标记下传部分

复制代码
void pushdown(int p){         mul(p<<1)=(mul(p<<1)*mul(p))%P;         mul(p<<1|1)=(mul(p<<1|1)*mul(p))%P;         add(p<<1)=(add(p<<1)*mul(p))%P;         add(p<<1|1)=(add(p<<1|1)*mul(p))%P;         sum(p<<1)=(sum(p<<1)*mul(p))%P;         sum(p<<