【牛客】树的距离 树上主席树

  • 题意
  • 思路
  • Code(709MS)

传送门:

题意

给 一 颗 树 , 求 以 x 为 子 树 中 , 距 离 x 大 于 等 于 k 的 点 与 x 的 距 离 和 。 给一颗树,求以x为子树中,距离x大于等于k的点与x的距离和。 给一颗树,求以x为子树中,距离x大于等于k的点与x的距离和。

思路

这 题 求 的 是 子 节 点 到 x 的 距 离 , 而 我 们 d f s 的 过 程 中 很 容 易 得 到 子 节 点 到 根 的 距 离 d i s 。 这题求的是子节点到x的距离,而我们dfs的过程中很容易得到子节点到根的距离dis。 这题求的是子节点到x的距离,而我们dfs的过程中很容易得到子节点到根的距离dis。

所 以 我 们 转 换 一 下 , 求 x 子 节 点 中 距 离 根 大 于 等 于 k + d i s [ x ] 的 点 与 x 的 距 离 和 。 所以我们转换一下,求x子节点中距离根大于等于k+dis[x]的点与x的距离和。 所以我们转换一下,求x子节点中距离根大于等于k+dis[x]的点与x的距离和。

假 设 我 们 知 道 个 数 为 s u m _ n u m , 这 些 点 距 离 根 的 和 为 s u m _ d i s 。 假设我们知道个数为sum\_num,这些点距离根的和为sum\_dis。 假设我们知道个数为sum_num,这些点距离根的和为sum_dis。
则 a n s = s u m _ d i s − s u m _ n u m ∗ d i s [ x ] 则ans=sum\_dis - sum\_num * dis[x] 则ans=sum_dis−sum_num∗dis[x]

怎 么 求 个 数 呢 ? 怎 么 求 大 于 等 于 k 的 点 的 个 数 呢 ? 怎么求个数呢?怎么求大于等于k的点的个数呢? 怎么求个数呢?怎么求大于等于k的点的个数呢?

我 们 可 以 利 用 主 席 树 帮 助 求 解 , 以 d i s [ x ] 为 叶 子 的 主 席 树 。 我们可以利用主席树帮助求解,以dis[x]为叶子的主席树。 我们可以利用主席树帮助求解,以dis[x]为叶子的主席树。
然 后 求 区 间 内 ≥ k 的 个 数 即 可 。 然后求区间内\ge k的个数即可。 然后求区间内≥k的个数即可。

这 里 有 几 个 小 细 节 : 这里有几个小细节: 这里有几个小细节:

  • d i s 的 大 小 会 爆 i n t , 所 以 我 们 需 要 离 散 化 进 而 建 席 树 dis的大小会爆int,所以我们需要离散化进而建席树 dis的大小会爆int,所以我们需要离散化进而建席树
  • d f s 序 建 主 席 树 , 因 为 是 树 上 dfs序建主席树,因为是树上 dfs序建主席树,因为是树上

最 后 , 这 题 需 要 一 定 的 代 码 能 力 。 最后,这题需要一定的代码能力。 最后,这题需要一定的代码能力。

Code(709MS)

#include "bits/stdc++.h"
using namespace std;typedef long long ll;const int N = 2e5 + 10;struct Edge {int v;ll w;
};vector<Edge> g[N];struct Tree {int l, r;ll sum, val;
}t[N * 40];
int root[N], cnt;vector<ll> v;
int getid(ll x) { return lower_bound(v.begin(), v.end(), x) - v.begin() + 1; }void insert(int pre, int &now, int l, int r, ll p, int val) {t[now = ++cnt] = t[pre];t[now].val += val;t[now].sum += v[p - 1];if(l == r) return ;int m = (l + r) >> 1;if(p <= m) insert(t[pre].l, t[now].l, l, m, p, val);else insert(t[pre].r, t[now].r, m + 1, r, p, val);
}void query(int pre, int now, int ql, int qr, int l, int r, ll &sum_num, ll &sum_dis) {if(ql <= l && r <= qr) {sum_num += t[now].val - t[pre].val;sum_dis += t[now].sum - t[pre].sum;return ;}int m = (l + r) >> 1;if(ql <= m) query(t[pre].l, t[now].l, ql, qr, l, m, sum_num, sum_dis);if(qr > m)  query(t[pre].r, t[now].r, ql, qr, m + 1, r, sum_num, sum_dis);
}int in[N], out[N], tim;
ll dis[N];
void dfs(int u, int fa) {in[u] = ++tim;v.push_back(dis[u]);for(auto e : g[u]) {int v = e.v;if(v == fa) continue;dis[v] = dis[u] + e.w;dfs(v, u);}out[u] = tim;
}void dfs2(int u, int fa, int cct) {insert(root[in[u] - 1], root[in[u]], 1, cct, getid(dis[u]), 1);for(auto e : g[u]) if(e.v != fa) dfs2(e.v, u, cct);
}void solve() {int n; cin >> n;for(int i = 2;i <= n; i++) {int p; ll d; cin >> p >> d;g[i].push_back(Edge{p, d});g[p].push_back(Edge{i, d});}dfs(1, 0);sort(v.begin(), v.end());v.erase(unique(v.begin(), v.end()), v.end());int cct = (int)v.size();dfs2(1, 0, cct);int m; cin >> m;while(m--) {int x; ll y; cin >> x >> y;y = dis[x] + y;int id = getid(y);if(id > cct) {cout << 0 << endl;continue;}ll sum_num = 0, sum_dis = 0;query(root[in[x] - 1], root[out[x]], id, cct, 1, cct, sum_num, sum_dis);cout << (ll)(sum_dis - sum_num * dis[x]) << endl;}
}signed main() {solve();
}

【牛客】树的距离 树上主席树相关推荐

  1. 牛客多校5 - Interval(主席树)

    题目链接:点击查看 题目大意:给出一个长度为 n 的数列 a ,规定函数 f( l , r ) = a[ l ] & a[ l + 1 ] & ... & a[ r ] ,在规 ...

  2. 牛客网 Cutting Bamboos 【主席树+二分】

    题意:给你n棵树,每棵树的高度是Hi,q次询问相互独立,每次询问{ l, r, x, y }, 就是在区间[l, r] 里的树需要y次全部砍完,每次砍可以选择一个高度,高于的地方全部砍掉,且要求每次砍 ...

  3. [牛客网#35D 树的距离]离散化+线段树合并

    [牛客网#35D 树的距离]离散化+线段树合并 分类:Data Structure SegMent Tree Merge 1. 题目链接 [牛客网#35D 树的距离] 2. 题意描述 wyf非常喜欢树 ...

  4. 牛客小白9 换个角度思考(离线+树状数组)

    title: 牛客小白9 换个角度思考(离线+树状数组) date: 2018-11-29 15:25:18 tags: [离线,树状数组] categories: ACM 题目链接 题目描述 给定一 ...

  5. BZOJ 2588 Spoj 10628 Count on a tree | 树上主席树

    BZOJ 2588 Count on a tree 题面 求树上两点之间路径上第k大的点权. 题解 一开始看到这道题觉得是树剖,然后又听说是主席树,然后以为是主席树+树剖,差点没吓死-- 然后发现,如 ...

  6. H - Hello Ms. Ze(树状数组套主席树,线段树上二分)

    H - Hello Ms. Ze 给定nnn种不同的材料,第iii种材料有aia_iai​个,有mmm个操作,操作分为两类: 把第xxx种材料修改为yyy个, 只用[l,r][l, r][l,r]区间 ...

  7. BZOJ1146[CTSC2008]网络管理——出栈入栈序+树状数组套主席树

    题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条 ...

  8. D-query SPOJ - DQUERY(求区间不同数的个数)(树状数组||线段树+离散)(主席树+在线)

    English Vietnamese Given a sequence of n numbers a1, a2, -, an and a number of d-queries. A d-query ...

  9. ICPC 徐州 H Yuuki and a problem (树状数组套主席树)

    Yuuki and a problem 先不管第一问的修改操作,考虑如何达到第二问的查询操作, 题目要我们给出一个区间[l,r][l, r][l,r]中,不能通过权值+++得到的最小的数字是什么, 假 ...

最新文章

  1. 从《黑客帝国》说起,我们如何证明这个世界不是一个系统?
  2. Spring Boot 内置Tomcat——IntelliJ IDEA中配置模块目录设为文档根目录(DocumentRoot)解决方案
  3. HTTP和HTTPS详解
  4. 学java的困惑_学习Java - 关于一些代码困惑
  5. 如何使用Python Flask编写Web服务
  6. tp5 前台页面获取url链接里的参数,如下
  7. (筆記) 如何增加SignalTap II能觀察的reg與wire數量? (SOC) (Quartus II) (SignalTap II)
  8. 程序员,别逼自己学 AI 了,掌握正确的方法,开发水平暴增!
  9. 姚前:算法经济与算法监管
  10. Wonderware Historian 2017安装,资料
  11. jquery中使用ajax的php实例
  12. 关于网络存储技术和存储的协议
  13. 程序员职场背锅甩锅指南
  14. 阿里云的认证费用是多少?考试要多长时间?
  15. dede模板加入php无法生成栏目,织梦后台更新后栏目无法生成,怎么办?
  16. web前端——div和span标签
  17. IP与域名之间的相互转换
  18. 不再贩卖「情怀」的锤子手机
  19. 如何使用edge给chrome下载官方插件
  20. owc报表控件 数据透视表_将数据透视图标题链接到报表过滤器

热门文章

  1. Keepalived原理
  2. OSGEarth显示经纬度标牌
  3. css給一个角加圆角,css圆角边框不起作用怎么办
  4. 机器学习可解释性(一)
  5. Day10 总结:产品开发必备的63个网站和工具
  6. 如何学习一种技能(总结)
  7. 推断因果关系理论(inferred causation)(下)
  8. MDG BRF字段值域合法性校验
  9. ArcGIS中如何生成超过2GB的渔网
  10. 模拟实现strlen,strcpy函数