题意:给定一棵树,边长为1,点带权。处理M个询问,格式为u,v,c,求从u走到v每次跳c步经过的点权之和,最后一步若不足c条边则直接走到v。N,M<=5w。
分成c>=sqrt(N)和c<sqrt(N)两种情况处理。若c>=sqrt(N),则显然步数不超过根号N步,然后模拟即可,如果是用的倍增的话一次询问就是sqrt(N)logN。不过claris上课讲了一个根号就能回答的方法,但是我忘啦。。对所有c<sqrt(N)的用简单的DP全部预处理出来,用lca的复杂度就可以回答询问了。但是这题越过lca的部分等等边界条件的处理非常恶心。。
但是倍增确实太慢了,并且代码一大坨,空间开销也大。其实爬树也可以用树链刨分的。把DFS序搞出来,然后不断向上找,直到要找的点与当前点在一条重链时他们的DFS序就一定是连续的,就可以回答了。链剖的常数比倍增小到哪儿去了。。考虑当数据构造等问题,阀值设得比sqrt(N)小会更快。。
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<assert.h>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define erp(i,a,b) for(int i=a;i>=b;--i)
c