一道比较综合的树上差分题,比较考验思维。
显然等差数列不好直接维护。
先考虑什么情况下会观察到玩家:
对于一条路径s-t
对于上升路径s->lca(s,t),上的任意一点x:
当:d[s]-d[x]=w[x] 时,这个人会被点x的观察员观察到。
这样的话,对于每个点x,我们考虑所有人的起点s,当d[s]=w[x]+d[x]时,这个学生能被x观察到。
这样就转化为了树上差分。(对于剩下的链 t -> lca(s,t) ,同理)
对于一个人的路径中:s->lca(s,t)上的点都插入一个值d[s].最后统计所有点x,这个点上等于w[x]+d[x]的值有多少个。
这里用树上差分+动态线段树+线段树合并即可维护。
但这样花费的空间是:2*n*logn 大约是2e7 ,这个空间可能不太够一般128MB最多开到3
e7,或者采用回收节点的方法把常数去掉(洛谷上看到的神奇的方法))
struct SeqTree{
int cnt,ls[N*40],rs[N*40],Max[N*40],id[N*40],rt[N],rab[N*40],tot,top,first[N]; joker s[N<<2];
inline void Insert(int x,int y,int op) //差分起始
{
s[++top]=(joker){first[x],y,op};
first[x]=top;
}
inline int New()
{
if(