COGS-2258 复仇的序幕曲(动态树分治)
来源:互联网 发布:matlab 无约束最优化 编辑:程序博客网 时间:2024/06/08 16:23
传送门:COGS-2258
题意:在一棵n个节点的树上进行m次询问:与u的距离不超过t的节点权值和
题解:动态树分治
每一层子树把节点按与根节点的距离排序,记录一下前缀和
#include<bits/stdc++.h>using namespace std;const int MX = 8e4 + 5;const int MXM = MX * 40;struct Tree { int n, sz; struct node { int dir, x; node(int dir = 0, int x = 0): dir(dir), x(x) {} bool operator<(const node& _A)const { return dir < _A.dir; } }; vector <node> ver; void init (int _n) { ver.clear(); n = _n; sz = 0; ver.resize(n + 1); } void add (int dir, int x) { ver[++sz] = node(dir, x); } int sum(int t) { if (ver.empty()) return 0; int p = upper_bound(ver.begin(), ver.end(), node(t)) - ver.begin() - 1; return ver[p].x; } void sort_presum() { if (ver.empty()) return; sort(ver.begin(), ver.end()); vector<node>tmp; int cnt = 0; tmp.push_back(node(-1, 0)); for (int i=0;i<ver.size();i++) { if (ver[i].dir != tmp[cnt].dir) { tmp.push_back(tmp[cnt++]); tmp[cnt].dir = ver[i].dir; tmp[cnt].x += ver[i].x; } else tmp[cnt].x += ver[i].x; } swap(ver, tmp); }} T[MX << 1];struct Edge { int v, w, nxt;} E[MX * 2];struct Root { int rt, subrt, dis, nxt;} root[MXM];int head[MX], fir[MX];int a[MX], vis[MX], sz[MX], id[MX];int n, m, tot, cnt, rear;void init() { memset(head, -1, sizeof(head)); memset(fir, -1, sizeof(fir)); memset(vis, 0, sizeof(vis)); tot = cnt = rear = 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, int 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, int tot, int &rt) { if (!rt && sz[u] * 2 > tot) rt = u; 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, tot, rt); sz[u] += sz[v]; }}void dfs_tree(int u, int fa, int rt, int subrt, int dir) { T[rt].add(dir, a[u]); T[subrt].add(dir, a[u]); add_root(u, rt, subrt, dir); 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) { int rt = 0; dfs_size(u, 0, 0, rt); dfs_size(u, 0, sz[u], rt = 0); vis[rt] = 1; id[rt] = ++cnt; T[cnt].init(sz[u]); T[cnt].add(0, a[rt]); add_root(rt, id[rt], 0, 0); for (int i = head[rt]; ~i; i = E[i].nxt) { int v = E[i].v; if (vis[v]) continue; T[++cnt].init(sz[v]); dfs_tree(v, rt, id[rt], cnt, E[i].w); T[cnt].sort_presum(); } T[id[rt]].sort_presum(); for (int i = head[rt]; ~i; i = E[i].nxt) { int v = E[i].v; if (vis[v]) continue; dfs(v); }}int Query(int u, int t) { int 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; if (t - dis >= 0) ret += T[rt].sum(t - dis) - T[subrt].sum(t - dis); } return ret;}int main() { freopen("SS.in", "r", stdin); freopen("SS.out", "w+", stdout); scanf("%d%d", &n, &m); 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); for (int i = 1, u, t; i <= m; i++) { scanf("%d%d", &u, &t); printf("%d\n", Query(u, t)); } return 0;}
阅读全文
0 0
- COGS-2258 复仇的序幕曲(动态树分治)
- COGS-2278 树黑白(动态树分治)
- COGS 577 蝗灾 线段树+CDQ分治
- 亚洲的复仇(上)
- 亚洲的复仇(下)
- 【点分治】【POJ 1741】【cogs 1714】树上的点对
- 例题:Abbott的复仇(UVa 816)
- 【COGS】577 蝗灾 cdq分治
- 【BZOJ4372】烁烁的游戏 动态树分治
- XDOJ-1009-Josephus环的复仇(线段树解约瑟夫环)
- 程序员的复仇方式
- Uva816 Abbott的复仇
- UVa816 Abbott的复仇
- Abbott的复仇 Uva816
- 我的编程序幕
- 大时代的序幕
- 1、流浪的序幕
- COGS-1715 [CQOI2011]动态逆序对(树状数组+线段树)
- Sticks Problem--(单调队列)
- MacOs下phpstorm Xdebug配置超详细
- SSL2689 2017年8月14日提高组T3 染色(树形dp)
- 网络流——最大流增广路算法
- shell编程 if语句
- COGS-2258 复仇的序幕曲(动态树分治)
- 计算机网络环境的搭建
- PTA-自测-4 Have Fun with Numbers
- Primer (四)
- 栈的应用——数制转换
- 51nod 1083 矩阵取数问题
- linux下挂载win问题
- Keras入门(2)——麻雀虽小,五脏俱全
- 正则表达式入门之字符匹配