运输 [树上差分, 整除分块]
+
对询问 , 在 处计算 到根节点路径上 的贡献, 再在 处减去多计算的贡献,
走过一条边 对答案的贡献为 , 其取值只有 种,
所以考虑 离线 所有询问, 在 走过 边 时, 整除分块 处理出 内所有取值, 在 树状数组 中 区间修改,
回溯时同上进行撤销操作, 在当前点计算所有关于该点的询问即可 .
#include<bits/stdc++.h>
#define reg register
#define pb push_back
typedef long long ll;
int read(){
char c;
int s = 0, flag = 1;
while((c=getchar()) && !isdigit(c))
if(c == '-'){ flag = -1, c = getchar(); break ; }
while(isdigit(c)) s = s*10 + c-'0', c = getchar();
return s * flag;
}
const int maxn = 1e5 + 10;
int N;
int M;
int num0;
int dep[maxn];
int fuck[maxn];
int head[maxn];
int Fk[maxn][20];
ll Ans[maxn];
struct Que{ int x, y; } ;
std::vector <Que> A[maxn];
struct Edge{ int nxt, to, w; } edge[maxn << 1];
void Add(int from, int to, int w){
edge[++ num0] = (Edge){ head[from], to, w };
head[from] = num0;
}
void DFS(int k, int fa){
dep[k] = dep[fa] + 1;
for(reg int i = 1; i <= 19; i ++) Fk[k][i] = Fk[Fk[k][i-1]][i-1];
for(reg int i = head[k]; i; i = edge[i].nxt){
int to = edge[i].to;
if(to == fa) continue ;
Fk[to][0] = k; DFS(to, k);
}
}
int Lca(int x, int y){
if(dep[x] < dep[y]) std::swap(x, y);
for(reg int i = 19; i >= 0; i --)
if(dep[Fk[x][i]] >= dep[y]) x = Fk[x][i];
if(x == y) return x;
for(reg int i = 19; i >= 0; i --)
if(Fk[x][i] != Fk[y][i]) x = Fk[x][i], y = Fk[y][i];
return Fk[x][0];
}
void init(int i){
int x = read(), y = read(); fuck[i] = read();
A[x].pb((Que){ i, 1 }), A[y].pb((Que){ i, 1 });
int lca = Lca(x, y); A[lca].pb((Que){ i, -2 });
Ans[i] = dep[x] + dep[y] - 2*dep[lca] + 1;
}
struct Bit_Tree{
int lim;
ll d[maxn], d2[maxn];
void Add(int k, ll x){ for(reg int i = k; i <= lim; i += (i&-i)) d[i] += x, d2[i] += 1ll*x*k; }
ll Ask(int k){
if(k <= 0) return 0;
ll s = 0;
for(reg int i = k; i; i -= (i&-i)) s += (1ll*k+1)*d[i] - d2[i];
return s;
}
void modify(const int &l, const int &r, const ll &x){ Add(l, x), Add(r+1, -x); }
ll query(const int &l, const int &r){ return Ask(r) - Ask(l-1); }
} bit_t;
void DFS_2(int k, int fa){
fa --;
for(reg int l = 1, r = 0; l <= fa; l = r+1){
r = fa/(fa/l);
bit_t.modify(l, r, fa/l);
}
int size = A[k].size();
for(reg int i = 0; i < size; i ++){
int id = A[k][i].x, opt = A[k][i].y;
Ans[id] += opt * bit_t.query(fuck[id], fuck[id]);
}
for(reg int i = head[k]; i; i = edge[i].nxt){
int to = edge[i].to;
if(to == Fk[k][0]) continue ;
DFS_2(to, edge[i].w);
}
for(reg int l = 1, r = 0; l <= fa; l = r+1){
r = fa/(fa/l);
bit_t.modify(l, r, -fa/l);
}
}
int main(){
N = read(), M = read();
for(reg int i = 1; i < N; i ++){
int u = read(), v = read(), d = read();
Add(u, v, d), Add(v, u, d);
}
DFS(1, 0);
for(reg int i = 1; i <= M; i ++) init(i);
bit_t.lim = 30000; DFS_2(1, 0);
for(reg int i = 1; i <= M; i ++) printf("%lld\n", Ans[i]);
return 0;
}