一、HDU-6162 Ch’s gift
思路:只要把主席树节点统计个数的意义改为累计所管辖区间的和就行了。剩下的部分就是裸的树上主席树了。
#include<bits/stdc++.h> using namespace std; #define MAXN 100010 #define LOGN 20 #define MAXQ 100010 #define LL long long typedef struct { int to, next; } Edge; LL v[MAXN], dv[MAXN * 3], n, q, dvcnt; LL par[MAXN][LOGN], depth[MAXN]; Edge edges[MAXN * 2]; int head[MAXN], ecnt; void init() { memset(head, -1, sizeof(head)); ecnt = 0; dvcnt = 0; } void add(int from, int to) { edges[ecnt].to = to; edges[ecnt].next = head[from]; head[from] = ecnt++; } void dfs4lca(int root, int f) { par[root][0] = f, depth[root] = depth[f] + 1; for(int i = head[root]; ~i; i = edges[i].next) { int to = edges[i].to; if(to != f)dfs4lca(to, root); } } void prepare4lca() { dfs4lca(1, 0); for(int d = 0; d + 1 < LOGN; ++d) { for(int i = 1; i <= n; ++i) { if(par[i][d] == 0)par[i][d + 1] = 0; else par[i][d + 1] = par[par[i][d]][d]; } } } int lca(int a, int b) { if(depth[a] < depth[b])swap(a, b); for(int i = LOGN - 1; i >= 0; i--) { int dif = depth[a] - depth[b]; if((dif >> i) & 1)a = par[a][i]; } if(a == b)return a; for(int i = LOGN - 1; i >= 0; --i) { if(par[a][i] != par[b][i]) { a = par[a][i], b = par[b][i]; } } return par[a][0]; } typedef struct { struct Node { int lch, rch; LL val; } nodes[MAXN * 20]; int root[MAXN], ncnt; void init() { memset(nodes, 0, sizeof(nodes)); memset(root, 0, sizeof(root)); ncnt = 0; } private: void update0(int& croot, int proot, LL val, int idx, int l, int r) { if(croot == 0) { croot = ++ncnt; nodes[croot].val = nodes[proot].val + val; } if(l == r)return; int mid = (l + r) >> 1; if(idx <= mid) { nodes[croot].rch = nodes[proot].rch; update0(nodes[croot].lch, nodes[proot].lch, val, idx, l, mid); } else { nodes[croot].lch = nodes[proot].lch; update0(nodes[croot].rch, nodes[proot].rch, val, idx, mid + 1, r); } } public: void insert(int x, LL val, int idx) { update0(root[x], root[par[x][0]], val, idx, 1, dvcnt); } private: LL query0(int qlrt, int qrrt, int da, int db, int l, int r) { if(l >= da && r <= db)return nodes[qrrt].val - nodes[qlrt].val; int mid = (l + r) >> 1; LL res = 0; if(da <= mid)res += query0(nodes[qlrt].lch, nodes[qrrt].lch, da, db, l, mid); if(db > mid)res += query0(nodes[qlrt].rch, nodes[qrrt].rch, da, db, mid + 1, r); return res; } public: LL query(int ql, int qr, int da, int db, bool left_close) { // printf("%d %d\n", ql, par[ql][0]); if(left_close)return query0(root[par[ql][0]], root[qr], da, db, 1, dvcnt); else return query0(root[ql], root[qr], da, db, 1, dvcnt); } } PerSegTree; struct qqq { int ql, qr, a, b; } qs[MAXQ]; #define indexOf(x) (lower_bound(dv + 1, dv + dvcnt + 1, x) - dv) PerSegTree pst; void buildPST(int root, int f) { pst.insert(root, v[root], indexOf(v[root])); for(int i = head[root]; ~i; i = edges[i].next) { int to = edges[i].to; if(to != f)buildPST(to, root); } } template<class T> inline void read(T& x) { bool s = 0; char t; while((t = getchar()) != ‘-‘ && (t < ‘0‘ || t > ‘9‘)); if(t == ‘-‘)s = 1, t = getchar(); x = t - ‘0‘; while((t = getchar()) >= ‘0‘ && t <= ‘9‘)x = x * 10 + (t ^ 48); if(s)x = -x; } int main() { // freopen("hdu6162.in", "r", stdin); int a, b; while(cin >> n >> q) { pst.init(); init(); for(int i = 1; i <= n; ++i)read(v[i]), dv[++dvcnt] = v[i]; for(int i = 1; i < n; ++i) { read(a), read(b); add(a, b); add(b, a); } for(int i = 1; i <= q; ++i) { read(qs[i].ql), read(qs[i].qr), read(qs[i].a), read(qs[i].b); dv[++dvcnt] = qs[i].a; dv[++dvcnt] = qs[i].b; } prepare4lca(); sort(dv + 1, dv + dvcnt + 1); dvcnt = unique(dv + 1, dv + dvcnt + 1) - dv; buildPST(1, 0); for(int i = 1; i <= q; ++i) { int s = qs[i].ql, t = qs[i].qr; int ilca = lca(s, t); LL sum = pst.query(ilca, s, indexOf(qs[i].a), indexOf(qs[i].b), 1) + pst.query(ilca, t, indexOf(qs[i].a), indexOf(qs[i].b), 0); cout << sum << (i == q ? ‘\n‘ : ‘ ‘); } } return 0; }
原文地址:https://www.cnblogs.com/dowhile0/p/9222609.html
时间: 2024-10-17 19:55:08