BZOJ4012 [HNOI2015]开店
2015-04-29 22:34
337 查看
首先这个叫"动态点分治",不过瞎YY也能YY出来【比如我。。。
就是记录下点分治的过程和每个点的答案信息,于是查询的时候只要沿着分治好的根一路走下去就行了,于是单次查询的外层复杂度是$O(log n)$的
对于每个点,要记录以从整棵树到它的分治路径和以它为根的子树内权值小于v的点到它的距离和(就是关于权值的前缀和)
于是查询一个点的时候只要二分一下就好了。。。
总复杂度$O((n + Q) * log^2n)$
写了一晚上QAQQQ
View Code
(p.s. bz上AC700T纪念!)
就是记录下点分治的过程和每个点的答案信息,于是查询的时候只要沿着分治好的根一路走下去就行了,于是单次查询的外层复杂度是$O(log n)$的
对于每个点,要记录以从整棵树到它的分治路径和以它为根的子树内权值小于v的点到它的距离和(就是关于权值的前缀和)
于是查询一个点的时候只要二分一下就好了。。。
总复杂度$O((n + Q) * log^2n)$
写了一晚上QAQQQ
/************************************************************** Problem: 4012 User: rausen Language: C++ Result: Accepted Time:28756 ms Memory:107560 kb ****************************************************************/ #include <cstdio> #include <algorithm> #include <vector> using namespace std; typedef long long ll; const int N = 15e4 + 4; inline int read(); inline void print(ll); struct edge { int next, to, v; edge(int _n = 0, int _t = 0, int _v = 0) : next(_n), to(_t), v(_v) {} } e[N << 1]; struct data { int v; ll dis; data(int _v = 0, ll _d = 0) : v(_v), dis(_d) {} inline bool operator < (const data &p) const { return v == p.v ? dis < p.dis : v < p.v; } }; struct Path { int p, s; ll dis; Path(int _p = 0, ll _d = 0, int _s = 0) : p(_p), dis(_d), s(_s) {} }; struct tree_node { int v, sz, mx, vis; vector <Path> path; vector <data> dis[3]; } tr ; int n, m, mod; int size, root; int first , tot; int L, R; ll ans; inline void Add_Edges(int x, int y, int z) { e[++tot] = edge(first[x], y, z), first[x] = tot; e[++tot] = edge(first[y], x, z), first[y] = tot; } #define y e[x].to void get_sz(int p, int fa) { int x; tr[p].sz = 1; for (x = first[p]; x; x = e[x].next) if (!tr[y].vis && y != fa) { get_sz(y, p); tr[p].sz += tr[y].sz; } } void get_rt(int p, int fa) { int x; tr[p].sz = 1, tr[p].mx = 0; for (x = first[p]; x; x = e[x].next) if (!tr[y].vis && y != fa) { get_rt(y, p); tr[p].sz += tr[y].sz; tr[p].mx = max(tr[p].mx, tr[y].sz); } tr[p].mx = max(tr[p].mx, size - tr[p].sz); if (tr[p].mx < tr[root].mx) root = p; } void calc(int p, int fa, int tar, int d, int now) { int x; tr[p].path.push_back(Path(tar, d, now)); tr[tar].dis[now].push_back(data(tr[p].v, d)); for (x = first[p]; x; x = e[x].next) if (!tr[y].vis && y != fa) calc(y, p, tar, d + e[x].v, now); } void work(int p) { int x, now = 0; tr[p].vis = 1; get_sz(p, 0); tr[p].path.push_back(Path(p, 0, 3)); for (x = first[p]; x; x = e[x].next) if (!tr[y].vis) calc(y, p, p, e[x].v, now++); for (x = first[p]; x; x = e[x].next) if (!tr[y].vis) { root = 0, size = tr[y].sz; get_rt(y, 0); work(root); } } #undef y inline ll query(vector <data> *v, ll d, int s) { static ll res; static int i, t; for (i = res = 0; i < 3; ++i) if (i != s) { t = lower_bound(v[i].begin(), v[i].end(), data(L, -1)) - v[i].begin(); if (t) res -= d * t + v[i][t - 1].dis; t = lower_bound(v[i].begin(), v[i].end(), data(R + 1, -1)) - v[i].begin(); if (t) res += d * t + v[i][t - 1].dis; } return res; } int main() { int i, j, k, x, y, z, Q, p; n = read(), Q = read(), mod = read(); for (i = 1; i <= n; ++i) tr[i].v = read(); for (i = 1; i < n; ++i) { x = read(), y = read(), z = read(); Add_Edges(x, y, z); } tr[root = 0].mx = size = n; get_rt(1, 0); work(root); for (i = 1; i <= n; ++i) for (j = 0; j < 3; ++j) { sort(tr[i].dis[j].begin(), tr[i].dis[j].end()); for (k = 1; k < tr[i].dis[j].size(); ++k) tr[i].dis[j][k].dis += tr[i].dis[j][k - 1].dis; } for (ans = 0; Q; --Q) { p = read(), L = (ans + read()) % mod, R = (ans + read()) % mod; if (L > R) swap(L, R); for (i = ans = 0; i < tr[p].path.size(); ++i) { if (L <= tr[tr[p].path[i].p].v && tr[tr[p].path[i].p].v <= R) ans += tr[p].path[i].dis; ans += query(tr[tr[p].path[i].p].dis, tr[p].path[i].dis, tr[p].path[i].s); } print(ans); } return 0; } inline int read() { static int x; static char ch; x = 0, ch = getchar(); while (ch < '0' || '9' < ch) ch = getchar(); while ('0' <= ch && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x; } inline void print(ll t) { static int tot, pr[20]; tot = 0; while (t) pr[++tot] = t % 10, t /= 10; if (!tot) putchar('0'); while (tot) putchar(pr[tot--] + '0'); putchar('\n'); }
View Code
(p.s. bz上AC700T纪念!)
相关文章推荐
- BZOJ 4012: [HNOI2015]开店
- 【动态树分治】【bzoj 4012】: [HNOI2015]开店
- bzoj 4012: [HNOI2015]开店 (树链剖分+主席树)
- BZOJ 4012 HNOI2015 开店 动态树分治+二分
- BZOJ4012 [HNOI2015]开店
- BZOJ 4012 HNOI 2015 开店(shop) 一道简单的点剖题
- bzoj4012 [HNOI2015]开店
- bzoj4012: [HNOI2015]开店
- 【BZOJ 4012】[HNOI2015]开店
- [BZOJ4012][HNOI2015]开店(动态点分治)
- BZOJ 4012: [HNOI2015]开店 -- 动态树分治
- bzoj4012 [HNOI2015]开店
- 【bzoj4012】 HNOI2015—开店
- BZOJ 4012 [HNOI2015]开店
- bzoj 4012: [HNOI2015]开店
- bzoj 4012: [HNOI2015]开店
- bzoj 4012: [HNOI2015]开店 主席树
- [BZOJ]4012: [HNOI2015]开店 树链剖分+主席树(线段树合并)
- BZOJ 4012 HNOI 2015 开店 动态点分治
- bzoj4012 [HNOI2015]开店