第二次写树链剖分 然后一直WA 一直WA 然后就对着标程改 终于在一下午和一晚上的折磨过后A了这道题 QAQ
首先把询问离线化 并按照值从大到小排序 对边的处理同理 这样我们就可以 只枚举每条边一次
然后对于线段树上的每一个节点 我们保存左边的1的长度 右边的1的长度 1的总长度 和根据f计算后的sum值
询问的时候找出x, y的LCA p 然后询问x到p的路径和y到p的路径 注意要把其中一条路径反转过来才能正常的询问 要注意特殊处理
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#define SF scanf
#define PF printf
#define ls (i<<1)
#define rs ((i<<1)|1)
using namespace std;
typedef long long LL;
const int MAXN = 100000;
const int INF = 0x3f3f3f3f;
int n, m, q, tx = 0;
int f[MAXN+10];
// Edges
struct node {
int v, next;
} Edge[MAXN*2+10];
int adj[MAXN+10], ecnt;
inline void addedge(int u, int v) {
node &e = Edge[++ecnt];
e.v = v; e.next = adj[u]; adj[u] = ecnt;
}
inline void add(int u, int v) {
addedge(u, v); addedge(v, u);
}
// DFS
int F[MAXN+10][20], son[MAXN+10], idx[MAXN+10], dep[MAXN+10];
int sz[MAXN+10], top[MAXN+10], dfn, length[MAXN+10];
void dfs(int u, int fa) {
son[u] = n+1; F[u][0] = fa; sz[u] = 1;
for(int i = 1; i < 20; i++) F[u][i] = F[F[u][i-1]][i-1];
for(int i = adj[u]; i; i = Edge[i].next) {
int v = Edge[i].v;
if(v == fa) continue;
dep[v] = dep[u] + 1;
dfs(v, u);
sz[u] += sz[v];
if(sz[v] > sz[son[u]]) son[u] = v;
}
if(son[u] == n+1) son[u] = u;
}
void Getid(int u, int tp) {
top[u] = tp;
if(son[u] != u) length[son[u]]++;
if(son[u] != u) Getid(son[u], top[u]);
for(int i = adj[u]; i; i = Edge[i].next) {
int v = Edge[i].v;
if(v == F[u][0] || v == son[u]) continue;
Getid(v, v);
}
}
void DFS(int u, int fa) {
if(u != son[u]) length[top[u]]++;
for(int i = adj[u]; i; i = Edge[i].next) {
int v = Edge[i].v;
if(v != fa) DFS(v, u);
}
}
// seg tree
struct Node {
int fr, ba, sum, len;
Node () {}
Node (int a, int b, int c, int d) : fr(a), ba(b), sum(c), len(d) {}
} ;
Node merge(Node a, Node b) {
Node ans;
ans.sum = a.sum + b.sum - f[a.ba] - f[b.fr] + f[a.ba+b.fr];
ans.len = a.len + b.len;
ans.fr = a.fr; ans.ba = b.ba;
if(a.fr == a.len) ans.fr += b.fr;
if(b.ba == b.len) ans.ba += a.ba;
return ans;
}
struct Seg_Tree {
Node tree[MAXN*4+10];
void Build(int i, int L, int R) {
Node &u = tree[i];
u.fr = u.ba = u.sum = 0;
u.len = R-L;
if(R-L == 1) return ;
int mid = (L+R) >> 1;
Build(ls, L, mid);
Build(rs, mid, R);
}
void add(int i, int L, int R, int x) {
Node &u = tree[i];
if(R-L == 1) {
u.fr = u.ba = 1; u.sum = f[1]; return ;
}
int mid = (L+R) >> 1;
if(x < mid) add(ls, L, mid, x);
else add(rs, mid, R, x);
u = merge(tree[ls], tree[rs]);
}
} seg;
// LCA
int Go(int x, int k) {
for(int i = 0; i <= 17; i++)
if((1<<i) & k)
x = F[x][i];
return x;
}
int LCA(int x, int y) {
if(dep[x] < dep[y]) swap(x, y);
x = Go(x, dep[x] - dep[y]);
if(x == y) return x;
for(int i = 17; i >= 0; i--)
if(F[x][i] != F[y][i])
x = F[x][i], y = F[y][i];
return F[x][0];
}
// Get Path imformation
Node GetNode(int l, int r, int i, int L, int R) {
if(l <= L && R <= r) return seg.tree[i];
if(R <= l || r <= L) return Node(0, 0, 0, 0);
int mid = (L+R) >> 1;
return merge(GetNode(l, r, ls, L, mid), GetNode(l, r, rs, mid, R));
}
bool act[MAXN+10];
Node Doit(int x, int y) {
Node ret(0, 0, 0, 0);
while(dep[x] > dep[y]) {
if(top[x] == x) {
if(act[x]) ret = merge(Node(1, 1, f[1], 1), ret);
else ret = merge(Node(0, 0, 0, 1), ret);
x = F[x][0];
}
else {
int R = idx[top[x]] + dep[x] - dep[top[x]];
int L = idx[top[x]];
if(top[x] == top[y]) L = idx[top[x]] + dep[y] - dep[top[x]];
ret = merge(GetNode(L, R, 1, 0, n), ret);
x = top[x];
}
}
return ret;
}
// Make an 0 to 1
void active(int u, int v) {
if(dep[u] < dep[v]) swap(u, v);
if(u != top[u]) seg.add(1, 0, n, idx[top[u]] + dep[u] - dep[top[u]] - 1);
else act[u] = true;
}
// Main
struct edge {
int u, v, wt;
bool operator < (const edge &t) const {
return wt < t.wt || (wt == t.wt && u < t.u) || (wt == t.wt && u == t.u && v < t.v);
}
} E[MAXN+10];
struct QUE {
int x, u, v, id;
bool operator < (const QUE &t) const {
return x < t.x || (x == t.x && u < t.u) || (x == t.x && u == t.u && v < t.v);
}
} Q[MAXN+10];
int Ans[MAXN+10];
int main() {
SF("%d%d", &n, &q);
seg.Build(1, 0, n);
for(int i = 1; i < n; i++) SF("%d", &f[i]);
for(int i = 1; i < n; i++) {
SF("%d%d%d", &E[i].u, &E[i].v, &E[i].wt);
add(E[i].u-1, E[i].v-1);
}
for(int i = 0; i < n; i++) top[i] = i;
dfs(0, 0);
Getid(0, 0);
DFS(0, 0);
int cnt = 0;
for(int i = 0; i < n; i++)
if(top[i] == i) {
idx[i] = cnt;
cnt += length[i];
}
for(int i = 1; i <= q; i++) {
SF("%d%d%d", &Q[i].u, &Q[i].v, &Q[i].x);
Q[i].id = i;
}
sort(E+1, E+n); sort(Q+1, Q+q+1);
reverse(E+1, E+n); reverse(Q+1, Q+1+q);
int P = 1;
for(int i = 1; i <= q; i++) {
while(P < n && E[P].wt >= Q[i].x) active(E[P].u-1, E[P].v-1), P++;
int u = Q[i].u-1, v = Q[i].v-1;
int lca = LCA(u, v);
if(u == lca) swap(u, v);
Node x = Doit(v, lca);
Node y = Doit(u, lca);
swap(x.fr, x.ba);
Node ret = merge(x, y);
Ans[Q[i].id] = ret.sum;
}
for(int i = 1; i <= q; i++) PF("%d\n", Ans[i]);
}