HDU 6162 - Ch’s gift | 2017 ZJUT Multi-University Training 9
/* HDU 6162 - Ch’s gift [ LCA,线段树 ] | 2017 ZJUT Multi-University Training 9 题意: N节点的树,Q组询问 每次询问s,t两节点之间的路径上点权值在[a,b]之间的点权总和 分析: 求出每个询问的LCA,然后离线 按dfs顺序更新树状数组,即某点处树状数组中存的值为其所有祖先节点的值 每个点处对答案的贡献为: 当其为第 i 个 lca 时, ans[i] -= 2 * query(a,b) , 再特判该节点 当其为第 i 个 s,t 时, ans[i] += query(a,b) */ #include <bits/stdc++.h> using namespace std; #define LL long long const int N = 1e5+5; typedef pair<int, int> P; vector<int> G[N];//存边 vector<P> QQ[N]; int a[N], b[N*4], cnt, n, Q; struct Query { int s, t, lca, a, b; }q[N]; void addedge(int u, int v) { G[u].push_back(v); } namespace LCA { struct Query { int v, q; }; vector <Query> query[N];//存每个点的询问 int ans[N], f[N], vis[N]; int sf(int x) { return x == f[x] ? x : f[x] = sf(f[x]); } void init() { memset(ans, -1, sizeof(ans)); for (int i = 0; i < N; i++) { vis[i] = 0; f[i] = i; query[i].clear(); } } void adq(int u, int v, int id) {//添加询问 query[u].push_back(Query{v, id}); query[v].push_back(Query{u, id}); } void LCA(int u) { f[u] = u, vis[u] = 1; for (auto& x : query[u]) { if (vis[x.v] && ans[x.q] == -1) ans[x.q] = sf(x.v); } for (auto& v : G[u]) { if (vis[v]) continue; LCA(v); f[v] = u; } } } void init2() { cnt = 0; for (int i = 1; i <= n; i++) b[++cnt] = a[i]; for (int i = 1; i <= Q; i++) { b[++cnt] = q[i].a; b[++cnt] = q[i].b; } sort(b+1, b+cnt+1); cnt = unique(b+1, b+cnt+1) - (b+1); for (int i = 1; i <= n; i++) a[i] = lower_bound(b+1, b+cnt+1, a[i]) - b; for (int i = 1; i <= Q; i++) { q[i].a = lower_bound(b+1, b+cnt+1, q[i].a) - b; q[i].b = lower_bound(b+1, b+cnt+1, q[i].b) - b; } } LL ans[N], c[N<<4]; void modify(int x, LL num){ while (x <= cnt) c[x] += num, x += x&-x; } LL sum(int x) { LL s = 0; while (x) s += c[x], x -= x&-x; return s; } void init() { memset(c, 0, sizeof(c)); for (int i = 0; i < N; i++) G[i].clear(); for (int i = 0; i < N; i++) QQ[i].clear(); memset(ans, 0, sizeof(ans)); } void dfs(int u, int pre) { modify(a[u], b[a[u]]); LL tmp; for (auto & qq : QQ[u]) { tmp = sum(q[qq.first].b) - sum(q[qq.first].a-1); if (qq.second == -1) { ans[qq.first] -= 2*tmp; if (a[u] >= q[qq.first].a && a[u] <= q[qq.first].b) ans[qq.first] += b[a[u]]; } else { ans[qq.first] += tmp; } } for (auto&v: G[u]) { if (v == pre) continue; dfs(v, u); } modify(a[u], -b[a[u]]); } int main() { int u, v; while (~scanf("%d%d", &n, &Q)) { init(); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); for (int i = 1; i < n; i++) { scanf("%d%d", &u, &v); addedge(u, v); addedge(v, u); } for (int i = 1; i <= Q; i++) scanf("%d%d%d%d", &q[i].s, &q[i].t, &q[i].a, &q[i].b); init2(); LCA::init(); for (int i = 1; i <= Q; i++) LCA::adq(q[i].s, q[i].t, i); LCA::LCA(1); for (int i = 1; i <= Q; i++) { q[i].lca = LCA::ans[i]; QQ[q[i].lca].push_back(P(i, -1)); QQ[q[i].s].push_back(P(i, 1)); QQ[q[i].t].push_back(P(i, 1)); } dfs(1, 1); for (int i = 1; i < Q; i++) printf("%lld ", ans[i]); printf("%lld\n", ans[Q]); } }
我自倾杯,君且随意