首先我们定义节点的状态0,1,2,3分别代表该节点分别接收到0,1,2,3个信号。
那么我们会发现,叶子节点的状态改变,会导致叶子节点到根的路径上一连串节点的状态改变。
比如当某叶子节点到根的路径上,
由叶子节点开始的若干个连续的节点均处于状态2,且该叶子节点处于激活状态,
那么此时,如果我们改变这一叶子节点的状态,
则从叶子节点开始,一路向根走,遇到的这些连续的2节点全部会变成状态1,
此外还要对应更新最后一个2节点的父节点。
因此,我们实质上就是要实现以下操作(单点修改之类的就不算了):
1.查询从根到某叶节点有多少个从叶节点开始的连续的1节点或2节点
2.把这些节点变成状态1或2
恩,于是我们可以树链剖分,用线段树维护本区间最右节点的状态,以及从本区间右端点开始有多少个连续的状态1或状态2节点即可。
具体细节见代码如下:
为什么我的代码这么慢啊
#include <bits/stdc++.h>
using namespace std;
char buf[25000000],*pp=buf;
#define getchar() *(pp++)
inline int read() {
int X=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9')w=(ch=='-'?-1:1),ch=getchar();
while(ch>='0'&&ch<='9')X=X*10+ch-'0',ch=getchar();
return X*w;
}
struct edge {
int v,p;
inline edge(int _v=0,int _p=0) {
v=_v;
p=_p;
}
} e[3000010];
int n,q,head[1500010],top,sr[6000010],siz[1500010],dep[1500010],w[1500010],tp[1500010],f[1500010],son[1500010],m,s[1500010],st[6000010],lazy[6000010];
inline void addedge(int u,