BZOJ-4012 开店(动态树分治)
来源:互联网 发布:怎么把知乎转到微信 编辑:程序博客网 时间:2024/04/29 16:11
传送门:BZOJ-4012
题意:给定一棵树,每个点有一个颜色,多次询问颜色在[l,r]区间内的所有点与某个点之间的距离之和
又是一个数组开小T到怀疑人生系列。。(我怎么总是管不住这双手root数组只开MX呢)
一个经典的动态树分治题目,用树状数组保存每种颜色的节点到该层子树的根节点的距离,然后一层一层计算就行。
= =本来应该是这样的,后来看了下发现颜色有n种,n^2logn的树状数组肯定爆内存啊。
后来想了下,明明只要记录区间内的值,用个vector弄下前缀和不就行了吗。。。(哈希都省去了
#include<cstdio>#include<string.h>#include<algorithm>#include<vector>using namespace std;typedef long long LL;typedef pair<int, int> PII;const int MX = 150005;const int MXM = MX * 40;const int inf = 0x3f3f3f3f;struct Edge { int v, w, nxt;} E[MX * 2];int head[MX], tot;struct node { int rt, subrt, nxt; LL dis;} root[MXM];struct p { int x; LL y, cnt; p(int x = 0, LL y = 0, LL cnt = 0): x(x), y(y), cnt(cnt) {} bool operator<(const p& _A)const { return x < _A.x; }};int fir[MX], rear;int a[MX], vis[MX], sz[MX], id[MX];int n, Root, Maxv, cnt;vector<p>T[MX << 2], tmp;void init() { memset(head, -1, sizeof(head)); memset(fir, -1, sizeof(fir)); memset(vis, 0, sizeof(vis)); tot = rear = cnt = 0;}void add_edge(int u, int v, int w) { E[tot].v = v; E[tot].w = w; E[tot].nxt = head[u]; head[u] = tot++;}void add_root(int u, int rt, int subrt, LL dis) { root[rear].rt = rt; root[rear].subrt = subrt; root[rear].dis = dis; root[rear].nxt = fir[u]; fir[u] = rear++;}void dfs_size(int u, int fa) { sz[u] = 1; for (int i = head[u]; ~i; i = E[i].nxt) { int v = E[i].v; if (vis[v] || v == fa) continue; dfs_size(v, u); sz[u] += sz[v]; }}void dfs_root(int u, int fa, int rt) { if (max(sz[u], sz[rt] - sz[u]) < Maxv) { Maxv = max(sz[u], sz[rt] - sz[u]); Root = u; } for (int i = head[u]; ~i; i = E[i].nxt) { int v = E[i].v; if (vis[v] || v == fa) continue; dfs_root(v, u, rt); }}p arr[MX];void cal(int u) { if (T[u].empty()) return; sort(T[u].begin(), T[u].end()); int sz = 0; arr[++sz] = p(-1, 0, 0); for (int i = 0; i < T[u].size(); i++) { if (T[u][i].x != arr[sz].x) { arr[++sz].x = T[u][i].x; arr[sz].y = arr[sz - 1].y + T[u][i].y; arr[sz].cnt = arr[sz - 1].cnt + 1; } else { arr[sz].y += T[u][i].y; arr[sz].cnt++; } } T[u].resize(sz); for (int i = 1; i <= sz; i++) T[u][i - 1] = arr[i];}void dfs_tree(int u, int fa, int rt, int subrt, LL dir) { add_root(u, rt, subrt, dir); T[rt].push_back(p(a[u], dir, 1)); T[subrt].push_back(p(a[u], dir, 1)); for (int i = head[u]; ~i; i = E[i].nxt) { int v = E[i].v; if (vis[v] || v == fa) continue; dfs_tree(v, u, rt, subrt, dir + E[i].w); }}void dfs(int u) { Root = 0; Maxv = n; dfs_size(u, -1); dfs_root(u, -1, u); vis[Root] = 1; id[Root] = ++cnt; T[cnt].clear(); T[cnt].push_back(p(a[Root], 0, 1)); add_root(Root, id[Root], 0, 0); for (int i = head[Root]; ~i; i = E[i].nxt) { int v = E[i].v; if (vis[v]) continue; T[++cnt].clear(); dfs_tree(v, Root, id[Root], cnt, E[i].w); cal(cnt); } cal(id[Root]); for (int i = head[Root]; ~i; i = E[i].nxt) { int v = E[i].v; if (vis[v]) continue; dfs(v); }}p Query(int rt, int l, int r) { if (T[rt].empty()) return p(); int p1 = lower_bound(T[rt].begin(), T[rt].end(), p(l)) - T[rt].begin() - 1; int p2 = upper_bound(T[rt].begin(), T[rt].end(), p(r)) - T[rt].begin() - 1; return p(0, T[rt][p2].y - T[rt][p1].y, T[rt][p2].cnt - T[rt][p1].cnt);}LL query(int u, int l, int r) { LL ret = 0; for (int i = fir[u]; ~i; i = root[i].nxt) { int rt = root[i].rt, subrt = root[i].subrt, dis = root[i].dis; p p1 = Query(rt, l, r); p p2 = Query(subrt, l, r); ret += p1.y - p2.y + (p1.cnt - p2.cnt) * dis; } return ret;}int main() { int m, A; //freopen("in.txt", "r", stdin); scanf("%d%d%d", &n, &m, &A); init(); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); for (int i = 1, u, v, w; i < n; i++) { scanf("%d%d%d", &u, &v, &w); add_edge(u, v, w); add_edge(v, u, w); } dfs(1); LL ans = 0; for (int i = 1, u, l, r; i <= m; i++) { scanf("%d%d%d", &u, &l, &r); l = (l + ans) % A; r = (r + ans) % A; if (l > r) swap(l, r); printf("%lld\n", ans = query(u, l, r)); } return 0;}
阅读全文
0 0
- BZOJ-4012 开店(动态树分治)
- 【动态树分治】【bzoj 4012】: [HNOI2015]开店
- BZOJ 4012: [HNOI2015]开店 -- 动态树分治
- BZOJ 4012 HNOI2015 开店 动态树分治+二分
- BZOJ 4012 HNOI 2015 开店 动态点分治
- [动态树分治] BZOJ4012 [HNOI2015]开店
- bzoj4012开店 动态点分治
- bzoj 4012: [HNOI2015]开店 (树链剖分+主席树)
- BZOJ 4012: [HNOI2015]开店
- BZOJ 4012 [HNOI2015]开店
- bzoj 4012 [HNOI2015]开店 【树链剖分】
- bzoj 3730: 震波 (动态点分治)
- 动态点分治系列(幻想乡战略游戏、开店、小清新数据结构题)
- [BZOJ]4012: [HNOI2015]开店 树链剖分+主席树(线段树合并)
- 【HNOI 2015 开店】【动态点分治 + 前缀和】
- 动态点分治:bzoj 3730,bzoj 1095
- BZOJ 3730: 震波 动态树分治 线段树 lca
- bzoj 4372: 烁烁的游戏 (动态点分治+线段树+LCA)
- C语言之模拟卖票
- 事务的四大隔离级别
- postgresql 解锁表总结
- 基于Android真实项目教你一步一步搭建架构2 -- Google官方Mvp架构
- linux, kill掉占用60%多cpu的进程,几秒后换个pid 和 command 又出现
- BZOJ-4012 开店(动态树分治)
- 快速查找素数
- PhotoShop使用
- 汇编小小的注意点
- 0814-Java接口
- 金币
- Android自定义图形-Shape的使用
- 【luogu1073】最优贸易(队列)
- RandomAccessFile的小demo IO进阶