Description

风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果。

由于她已经DT FC 了The big black,  她觉得这个游戏太简单了,于是发明了一个更

加难的版本。首先有一个地图,是一棵由 n 个顶点、n-1 条边组成的树(例如图 1

给出的树包含 8 个顶点、7 条边)。这颗树上有 P 个盘子,每个盘子实际上是一条

路径(例如图 1 中顶点 6 到顶点 8 的路径),并且每个盘子还有一个权值。第 i 个

盘子就是顶点a_i到顶点b_i的路径(由于是树,所以从a_i到b_i的路径是唯一的),

权值为c_i。接下来依次会有Q个水果掉下来,每个水果本质上也是一条路径,第

i 个水果是从顶点 u_i 到顶点v_i 的路径。幽香每次需要选择一个盘子去接当前的水

果:一个盘子能接住一个水果,当且仅当盘子的路径是水果的路径的子路径(例如

图1中从 3到7 的路径是从1到8的路径的子路径)。这里规定:从a 到b的路径与

从b到 a的路径是同一条路径。当然为了提高难度,对于第 i 个水果,你需要选择

能接住它的所有盘子中,权值第 k_i 小的那个盘子,每个盘子可重复使用(没有使用次数

的上限:一个盘子接完一个水果后,后面还可继续接其他水果,只要它是水

果路径的子路径)。幽香认为这个游戏很难,你能轻松解决给她看吗?

Input

第一行三个数 n和P 和Q,表示树的大小和盘子的个数和水果的个数。

接下来n-1 行,每行两个数 a、b,表示树上的a和b 之间有一条边。树中顶点

按1到 n标号。 接下来 P 行,每行三个数 a、b、c,表示路径为 a 到 b、权值为 c 的盘子,其

中0≤c≤10^9,a不等于b。

接下来Q行,每行三个数 u、v、k,表示路径为 u到 v的水果,其中 u不等于v,你需要选择第 k小的盘子,

第k 小一定存在。

Output

对于每个果子,输出一行表示选择的盘子的权值。

Sample Input

10 10 10 
1 2 
2 3 
3 4 
4 5 
5 6 
6 7 
7 8 
8 9 
9 10 
3 2 217394434 
10 7 13022269 
6 7 283254485 
6 8 333042360 
4 6 442139372 
8 3 225045590 
10 4 922205209 
10 8 808296330 
9 2 486331361 
4 9 551176338 
1 8 5 
3 8 3 
3 8 4 
1 8 3 
4 8 1 
2 3 1 
2 3 1 
2 3 1 
2 4 1 
1 4 1

Sample Output

442139372 
333042360 
442139372 
283254485 
283254485 
217394434 
217394434 
217394434 
217394434 
217394434

HINT

N,P,Q<=40000。

题解

(部分内容来自thy_asdf)

我们考虑如果这个题不出在树上,而在序列上,很容易想到用$cdq$来解决。

我们想办法将树拍成一条链,通常办法是$dfs$序(其实树剖的实质也是$dfs$序),再试图找到他们之间的$dfs$序关系。

对于一条路径的子路径,在有根树上只有两种情况。我们分别考虑两种情况(记号说明:$dfn_u$表示$u$的$dfs$序,$last_u$表示以$u$为根的子树中$dfs$序最大的值):

1. 子路径经过整条路径的$lca$:

如上图所示,假设子路径$u<->v$在路径$a<->b$上。显然$a,b$分别在以$u,v$为根的子树中。

不妨设$dfn_u<=dfn_v$,$dfn_a<=dfn_b$,由$dfs$序的性质,显然存在不等式:$dfn_u<=dfn_a<=last_u$,$dfn_v<=dfn_b<=last_v$。

2. 子路径不经过整条路径的$lca$:

我们记节点$u$在路径$u<->v$上的儿子是$w$。

同样的,容易发现,路径$a<->b$若包含$u<->v$肯定需要$a$或$b$其中一个是在以$v$为根的子树中。不妨假设这个点是$a$。

那么$b$应满足:不在以$w$为根的子树中即可。

显然就有$dfn_v<=dfn_a<=last_v$,$1<=dfn_b<=dfn_w-1 \cup last_w+1<=dfn_b<=n$。

那么现在题目就转化成了不等式之间的关系,考虑$cdq$,我们需要解决的问题就是一个实数对$(dfn_a,dfn_b)$满足不等式组的个数。

继续转化,将需要同时满足的两个不等式抽象成二位空间内的一个矩形,只要点$(dfn_a,dfn_b)$在某个矩形内,就能满足这个不等式组。

现在,整个题目就是覆盖一个点的矩形中权值第$k$小的权值是多少。

将矩形按权值从小到大排序,用扫描线的思想,树状数组区间修改即可。

  1 //It is made by Awson on 2017.12.30
  2 #include <map>
  3 #include <set>
  4 #include <cmath>
  5 #include <ctime>
  6 #include <queue>
  7 #include <stack>
  8 #include <vector>
  9 #include <cstdio>
 10 #include <string>
 11 #include <cstdlib>
 12 #include <cstring>
 13 #include <iostream>
 14 #include <algorithm>
 15 #define LL long long
 16 #define LD long double
 17 #define Max(a, b) ((a) > (b) ? (a) : (b))
 18 #define Min(a, b) ((a) < (b) ? (a) : (b))
 19 #define lowbit(x) ((x)&(-(x)))
 20 using namespace std;
 21 const int N = 80000;
 22
 23 int n, p, q, ans[N+5];
 24 int st[N+5], ed[N+5];
 25 namespace LCA {
 26     struct tt {
 27     int to, next;
 28     }edge[(N<<1)+5];
 29     int path[N+5], tot, u, v, dfn;
 30     int top[N+5], size[N+5], son[N+5], fa[N+5], dep[N+5];
 31     void add(int u, int v) {
 32     edge[++tot].to = v;
 33     edge[tot].next = path[u];
 34     path[u] = tot;
 35     }
 36     void dfs1(int u, int father, int depth) {
 37     fa[u] = father, size[u] = 1, dep[u] = depth;
 38     for (int i = path[u]; i; i = edge[i].next)
 39         if (edge[i].to != father) {
 40         dfs1(edge[i].to, u, depth+1);
 41         size[u] += size[edge[i].to];
 42         if (size[edge[i].to] >= size[son[u]]) son[u] = edge[i].to;
 43         }
 44     }
 45     void dfs2(int u, int tp) {
 46     top[u] = tp; st[u] = ++dfn;
 47     if (son[u]) dfs2(son[u], tp);
 48     for (int i = path[u]; i; i = edge[i].next)
 49         if (edge[i].to != fa[u] && edge[i].to != son[u])
 50         dfs2(edge[i].to, edge[i].to);
 51     ed[u] = dfn;
 52     }
 53     int get_son(int u, int v) {
 54     int last = 0;
 55     while (top[u] != top[v]) {
 56         last = top[v];
 57         v = fa[last];
 58     }
 59     return u == v ? last : son[u];
 60     }
 61     int query(int u, int v) {
 62     while (top[u] != top[v]) {
 63         if (dep[top[u]] < dep[top[v]]) swap(u, v);
 64         u = fa[top[u]];
 65     }
 66     return dep[u] < dep[v] ? u : v;
 67     }
 68     void main() {
 69     for (int i = 1; i < n; i++) {
 70         scanf("%d%d", &u, &v);
 71         add(u, v), add(v, u);
 72     }
 73     dfs1(1, 0, 1); dfs2(1, 1);
 74     }
 75 }
 76 namespace CDQ {
 77     struct tt {
 78     int x1, x2, y1, y2, k;
 79     tt() {
 80     }
 81     tt(int _x1, int _x2, int _y1, int _y2, int _k) {
 82         x1 = _x1, y1 = _y1, x2 = _x2, y2 = _y2, k = _k;
 83     }
 84     bool operator < (const tt &b) const {
 85         return k < b.k;
 86     }
 87     }opt[N+5];
 88     struct ss {
 89     int x, y, k, id;
 90     ss() {
 91     }
 92     ss(int _x, int _y, int _k, int _id) {
 93         x = _x, y = _y, k = _k, id = _id;
 94     }
 95     bool operator < (const ss &b) const {
 96         return x < b.x;
 97     }
 98     }query[N+5], qu1[N+5], qu2[N+5];
 99     int u, v, k, P;
100     struct ttt {
101     int x, y, val;
102     ttt() {
103     }
104     ttt(int _x, int _y, int _val) {
105         x = _x, y = _y, val = _val;
106     }
107     bool operator < (const ttt &b) const {
108         return x < b.x;
109     }
110     }doit[(N<<1)+5];
111     struct bit_tree {
112     int c[N+5];
113     void add(int x, int val) {
114         for (; x <= n; x += lowbit(x)) c[x] += val;
115     }
116     int count(int x) {
117         int ans = 0;
118         for (; x; x -= lowbit(x)) ans += c[x];
119         return ans;
120     }
121     }T;
122     void solve(int ql, int qr, int pl, int pr) {
123      if (pl == pr) {
124         for (int i = ql; i <= qr; i++) ans[query[i].id] = opt[pl].k;
125         return;
126     }
127     int mid = (pl+pr)>>1, cnt = 0, pos = 0, q1 = 0, q2 = 0;
128     for (int i = pl; i <= mid; i++) {
129         doit[++cnt] = ttt(opt[i].x1, opt[i].y1, 1);
130         doit[++cnt] = ttt(opt[i].x1, opt[i].y2+1, -1);
131         doit[++cnt] = ttt(opt[i].x2+1, opt[i].y1, -1);
132         doit[++cnt] = ttt(opt[i].x2+1, opt[i].y2+1, 1);
133     }
134     sort(doit+1, doit+1+cnt);
135     for (int i = ql; i <= qr; i++) {
136         while (pos < cnt && doit[pos+1].x <= query[i].x) pos++, T.add(doit[pos].y, doit[pos].val);
137         int tmp = T.count(query[i].y);
138          if (query[i].k <= tmp) qu1[++q1] = query[i];
139         else query[i].k -= tmp, qu2[++q2] = query[i];
140     }
141     while (pos < cnt) pos++, T.add(doit[pos].y, doit[pos].val);
142     for (int i = 1; i <= q1; i++) query[i+ql-1] = qu1[i];
143     for (int i = 1; i <= q2; i++) query[i+q1+ql-1] = qu2[i];
144     if (q1) solve(ql, ql+q1-1, pl, mid);
145     if (q2) solve(ql+q1, qr, mid+1, pr);
146     }
147     void main() {
148     for (int i = 1; i <= p; i++) {
149         scanf("%d%d%d", &u, &v, &k);
150         if (st[u] > st[v]) swap(u, v);
151         int w = LCA::query(u, v);
152         if (u == w) {
153         w = LCA::get_son(u, v);
154         if (st[w] > 1) opt[++P] = tt(1, st[w]-1, st[v], ed[v], k);
155         if (ed[w] < n) opt[++P] = tt(st[v], ed[v], ed[w]+1, n, k);
156         }else opt[++P] = tt(st[u], ed[u], st[v], ed[v], k);
157     }
158     p = P;
159     for (int i = 1; i <= q; i++) {
160         scanf("%d%d%d", &u, &v, &k);
161         if (st[u] > st[v]) swap(u, v);
162         query[i] = ss(st[u], st[v], k, i);
163     }
164     sort(opt+1, opt+1+p); sort(query+1, query+1+q);
165         solve(1, q, 1, p);
166     }
167 }
168
169 void work() {
170     scanf("%d%d%d", &n, &p, &q);
171     LCA::main();
172     CDQ::main();
173     for (int i = 1; i <= q; i++) printf("%d\n", ans[i]);
174 }
175 int main() {
176     work();
177     return 0;
178 }

转载于:https://www.cnblogs.com/NaVi-Awson/p/8150418.html

[HNOI 2015]接水果相关推荐

  1. 【HNOI 2015 开店】【动态点分治 + 前缀和】

    题意:给出一个 n个点的树,每条边有长度,每个点有点权.有 q 个询问,每个询问查询点 u 到所有权值在 [l, r] 中的点的距离之和. 强制在线. 和幻想乡战略游戏差不多. 精髓在前缀和的应用上. ...

  2. 小蚂蚁学习mysql性能优化(8)--数据库结构优化--范式化和反范式化,水平分表,垂直分表...

    2019独角兽企业重金招聘Python工程师标准>>> 范式化和反范式化 范式化是指数据库设计的规范,目前说到范式化一般是指第三设计范式,也就是要求数据表中不存在非关键字段对任意候选 ...

  3. 拓扑排序三题(菜肴制作杂物最大食物链计数)

    目录 一.[HNOI]2015菜肴制作 二.洛谷1113杂物 代码一: 代码二: 三.最大食物链计数[洛谷4017] DAG:有向无环图 图的建立很重要 一.[HNOI]2015菜肴制作 传送门1 思 ...

  4. Apache Cassandra架构理解

    架构 基本流程: 点对点分布式系统,集群中各节点平等,数据分布于集群中各节点,各节点间每秒交换一次信息. 每个节点的commit log提交日志捕获写操作来确保数据持久性. 数据先被写入MemTabl ...

  5. 用Python分析了1980~2015年考研英语真题词汇,原来考研英语应该这样考!

    微信改版,加星标不迷路! 用Python分析了1980~2015年考研英语真题词汇,原来考研应该这样考! 作者:阿广 概述 前言 数据介绍 实现过程 考研英语词汇统计分析 搞笑一刻 阿广说 每日问题 ...

  6. HNUSTOJ-1674 水果消除(搜索或并查集)

    1674: 水果消除 时间限制: 2 Sec  内存限制: 128 MB 提交: 335  解决: 164 [提交][状态][讨论版] 题目描述 "水果消除"是一款手机游戏,相信大 ...

  7. 零距离感受2015年安全***大赛:静动之美 ***兼备

    2015年5月下旬的武汉,小雨霏霏.某酒店数百平米的会议大厅里,摆着四十多张桌子,每三人一组面对面坐着,每人面前都摆着一台笔记本--这样的场景维持了5个多小时.与其说这是一场比赛,看起来更像是一个会议 ...

  8. 中国水果加工行业产销格局与开发价值分析报告2022版

    中国水果加工行业产销格局与开发价值分析报告2022版 HS--HS--HS--HS--HS--HS--HS--HS--HS--HS--HS--HS-- [修订日期]:2021年11月 [搜索鸿晟信合研 ...

  9. “隐忍”多年的“水果大王”百果园要寻求资本协助了?

    文 | 古海归人 来源 | 螳螂财经(ID:TanglangFin) 6月1日,"隐忍"多年的百果园向证监会递交了上市申请的材料,启动了境外上市程序. 深圳百果园实业(集团)股份有 ...

最新文章

  1. 约瑟夫死亡游戏算法问题
  2. Python使用SQLAlchemy连接数据库并创建数据表、插入数据、删除数据、更新表、查询表(CRUD)
  3. Kogito,ergo规则—第2部分:规则的全面执行模型
  4. pillow api
  5. Android中通过ViewHelper.setTranslationY实现View移动控制(NineOldAndroids开源项目)
  6. imagemagick, imagick和magickwand的安装
  7. 基于matlab和lingo的数学实验,MATLAB和LINGO软件在数学建模竞赛中的应用-精选教育文档...
  8. python实现一个简单的tftp客户端
  9. 敏感词测试软件,作者敏感词检测工具
  10. 公众号如何涨粉?会其中一种都可以让你爆粉
  11. ibm服务器维修检测报告,启创云小机(IBM POWER7)测试报告
  12. 开课吧python基础语法-零基础玩转Python
  13. 物联网已经发展多年,为什么一直不温不火
  14. 数据预处理 - 类型转换(离散型)
  15. 教育类小程序APP开发
  16. getchar()用法 与 getch()函数使用方法
  17. QQ空间将不再支持免费备份原图?附QQ空间相册导出工具合集
  18. 西安市中考计算机技术,2021年西安市中考信息技术练习题(三)
  19. excel转换成pdf java_Java基于Spire Cloud Excel把Excel转换成PDF
  20. 北京交大计算机学院师资,赵瑞珍(计算机与信息技术学院)老师 - 北京交通大学 - 院校大全...

热门文章

  1. Ansible Playbook企业案例:利用 playbook 安装 nginx、安装和卸载 httpd、安装mysql
  2. Django 3.2.5博客开发教程:体验数据查询
  3. 【收藏】在 Linux 上以 All-in-One 模式安装 KubeSphere
  4. 请解释为什么集合类没有实现Cloneable和Serializable接口?
  5. MySQL多表与分组练习题及答案
  6. Docker镜像上传至私有仓库
  7. Starting MySQL.... ERROR! The server quit without updating PID file
  8. [BX] 和 loop指令
  9. C++ 输出当前所在的路径
  10. css常用样式汇总记录