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$小的权值是多少。

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

 //It is made by Awson on 2017.12.30
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define LD long double
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int N = ; int n, p, q, ans[N+];
int st[N+], ed[N+];
namespace LCA {
struct tt {
int to, next;
}edge[(N<<)+];
int path[N+], tot, u, v, dfn;
int top[N+], size[N+], son[N+], fa[N+], dep[N+];
void add(int u, int v) {
edge[++tot].to = v;
edge[tot].next = path[u];
path[u] = tot;
}
void dfs1(int u, int father, int depth) {
fa[u] = father, size[u] = , dep[u] = depth;
for (int i = path[u]; i; i = edge[i].next)
if (edge[i].to != father) {
dfs1(edge[i].to, u, depth+);
size[u] += size[edge[i].to];
if (size[edge[i].to] >= size[son[u]]) son[u] = edge[i].to;
}
}
void dfs2(int u, int tp) {
top[u] = tp; st[u] = ++dfn;
if (son[u]) dfs2(son[u], tp);
for (int i = path[u]; i; i = edge[i].next)
if (edge[i].to != fa[u] && edge[i].to != son[u])
dfs2(edge[i].to, edge[i].to);
ed[u] = dfn;
}
int get_son(int u, int v) {
int last = ;
while (top[u] != top[v]) {
last = top[v];
v = fa[last];
}
return u == v ? last : son[u];
}
int query(int u, int v) {
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) swap(u, v);
u = fa[top[u]];
}
return dep[u] < dep[v] ? u : v;
}
void main() {
for (int i = ; i < n; i++) {
scanf("%d%d", &u, &v);
add(u, v), add(v, u);
}
dfs1(, , ); dfs2(, );
}
}
namespace CDQ {
struct tt {
int x1, x2, y1, y2, k;
tt() {
}
tt(int _x1, int _x2, int _y1, int _y2, int _k) {
x1 = _x1, y1 = _y1, x2 = _x2, y2 = _y2, k = _k;
}
bool operator < (const tt &b) const {
return k < b.k;
}
}opt[N+];
struct ss {
int x, y, k, id;
ss() {
}
ss(int _x, int _y, int _k, int _id) {
x = _x, y = _y, k = _k, id = _id;
}
bool operator < (const ss &b) const {
return x < b.x;
}
}query[N+], qu1[N+], qu2[N+];
int u, v, k, P;
struct ttt {
int x, y, val;
ttt() {
}
ttt(int _x, int _y, int _val) {
x = _x, y = _y, val = _val;
}
bool operator < (const ttt &b) const {
return x < b.x;
}
}doit[(N<<)+];
struct bit_tree {
int c[N+];
void add(int x, int val) {
for (; x <= n; x += lowbit(x)) c[x] += val;
}
int count(int x) {
int ans = ;
for (; x; x -= lowbit(x)) ans += c[x];
return ans;
}
}T;
void solve(int ql, int qr, int pl, int pr) {
if (pl == pr) {
for (int i = ql; i <= qr; i++) ans[query[i].id] = opt[pl].k;
return;
}
int mid = (pl+pr)>>, cnt = , pos = , q1 = , q2 = ;
for (int i = pl; i <= mid; i++) {
doit[++cnt] = ttt(opt[i].x1, opt[i].y1, );
doit[++cnt] = ttt(opt[i].x1, opt[i].y2+, -);
doit[++cnt] = ttt(opt[i].x2+, opt[i].y1, -);
doit[++cnt] = ttt(opt[i].x2+, opt[i].y2+, );
}
sort(doit+, doit++cnt);
for (int i = ql; i <= qr; i++) {
while (pos < cnt && doit[pos+].x <= query[i].x) pos++, T.add(doit[pos].y, doit[pos].val);
int tmp = T.count(query[i].y);
if (query[i].k <= tmp) qu1[++q1] = query[i];
else query[i].k -= tmp, qu2[++q2] = query[i];
}
while (pos < cnt) pos++, T.add(doit[pos].y, doit[pos].val);
for (int i = ; i <= q1; i++) query[i+ql-] = qu1[i];
for (int i = ; i <= q2; i++) query[i+q1+ql-] = qu2[i];
if (q1) solve(ql, ql+q1-, pl, mid);
if (q2) solve(ql+q1, qr, mid+, pr);
}
void main() {
for (int i = ; i <= p; i++) {
scanf("%d%d%d", &u, &v, &k);
if (st[u] > st[v]) swap(u, v);
int w = LCA::query(u, v);
if (u == w) {
w = LCA::get_son(u, v);
if (st[w] > ) opt[++P] = tt(, st[w]-, st[v], ed[v], k);
if (ed[w] < n) opt[++P] = tt(st[v], ed[v], ed[w]+, n, k);
}else opt[++P] = tt(st[u], ed[u], st[v], ed[v], k);
}
p = P;
for (int i = ; i <= q; i++) {
scanf("%d%d%d", &u, &v, &k);
if (st[u] > st[v]) swap(u, v);
query[i] = ss(st[u], st[v], k, i);
}
sort(opt+, opt++p); sort(query+, query++q);
solve(, q, , p);
}
} void work() {
scanf("%d%d%d", &n, &p, &q);
LCA::main();
CDQ::main();
for (int i = ; i <= q; i++) printf("%d\n", ans[i]);
}
int main() {
work();
return ;
}

[HNOI 2015]接水果的更多相关文章

  1. [HNOI 2015]实验比较

    Description 小D 被邀请到实验室,做一个跟图片质量评价相关的主观实验.实验用到的图片集一共有 N 张图片,编号为 1 到 N.实验分若干轮进行,在每轮实验中,小 D会被要求观看某两张随机选 ...

  2. [HNOI 2015]亚瑟王

    Description 小 K 不慎被 LL 邪教洗脑了,洗脑程度深到他甚至想要从亚瑟王邪教中脱坑. 他决定,在脱坑之前,最后再来打一盘亚瑟王.既然是最后一战,就一定要打得漂 亮.众所周知,亚瑟王是一 ...

  3. [HNOI 2015]开店

    Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现 ...

  4. [HNOI 2015]菜肴制作

    Description 知名美食家小 A被邀请至ATM 大酒店,为其品评菜肴. ATM 酒店为小 A 准备了 N 道菜肴,酒店按照为菜肴预估的质量从高到低给予 1到N的顺序编号,预估质量最高的菜肴编号 ...

  5. [HNOI 2015]落忆枫音

    Description 「恒逸,你相信灵魂的存在吗?」 郭恒逸和姚枫茜漫步在枫音乡的街道上.望着漫天飞舞的红枫,枫茜突然问出 这样一个问题.  「相信吧.不然我们是什么,一团肉吗?要不是有灵魂……我们 ...

  6. 【题解】亚瑟王 HNOI 2015 BZOJ 4008 概率 期望 动态规划

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4008 一道不简单的概率和期望dp题 根据期望的线性性质,容易想到,可以算出每张卡的期望伤害, ...

  7. 解题:HNOI 2015 开店

    题面 根据树上距离的计算方法,可以先把答案化成$\sum dep_i+n*dep_u-\sum 2*dep[LCA(i,u)]$的形式,然后维护$\sum 2*dep[LCA(i,u)]$ 把妖怪们按 ...

  8. 「HNOI 2015」实验比较

    \(Description\) 有\(n\)个元素,对于每个元素\(x_i\)最多知道一个形如\(x_j < x_i\)或\(x_j=x_i\)的条件,问有多少合法的序列.合法的序列满足每个元素 ...

  9. [BZOJ 4010][HNOI 2015] 菜肴制作

    4010: [HNOI2015]菜肴制作 Time Limit: 5 Sec  Memory Limit: 512 MBSubmit: 1776  Solved: 889[Submit][Status ...

随机推荐

  1. CountDownLatch 源码解析—— await()

    上一篇文章说了一下CountDownLatch的使用方法.这篇文章就从源码层面说一下await() 的原理. 我们已经知道await 能够让当前线程处于阻塞状态,直到锁存器计数为零(或者线程中断). ...

  2. 计算1-1/3+1/5-1/7+···的前n项和

    这图1为书里的教材,图二为自己打的程序 (1)二者相比,自己写的代码显得更短,听说代码写的越精简越好,但是自己的较难分析,他人看来可能会较难理解一点:(自己在第一次运行时将for()中的第二个表达式写 ...

  3. lambda及参数绑定

    一.介绍   对于STL中的算法,我们都可以传递任何类别的可调用对象.对于一个对象或一个表达式,如果可以对其使用调用运算符,则称它为可调用的.即,如果e是一个可调用的表达式,则我们可以编写代码e(ar ...

  4. formidable 表单文件和数据提交

    只要涉及文件上传,那么form标签要加一个属性: <form action="http://127.0.0.1/dopost" method="post" ...

  5. 项目Beta冲刺Day4

    项目进展 李明皇 今天解决的进度 因服务器端未完成登录态维护,故无法进行前后端联动. 明天安排 前后端联动调试 林翔 今天解决的进度 因上课和实验室事务未完成登录态维护 明天安排 完成登录态维护 孙敏 ...

  6. slf4j 与 log4j2 实战讲解与日志分割

    这两天搭建项目的时候用到log4j2在这里把自己的问题与了解拿出来与大家分享一下. 1.为什我要用 因为,使用slf4j可以很好的保证我们的日志系统具有良好的兼容性,兼容当前常见几种日志系统,而使用l ...

  7. 分布式版本控制系统Git的安装及使用

    Git的安装分为客户端安装和服务端安装,鉴于我平时码代码在windows环境下,因此本文客户端安装直接在windows环境,服务端安装在linux环境下(centos). Git客户端安装 客户端下载 ...

  8. 《深入实践Spring Boot》阅读笔记之三:核心技术源代码分析

    刚关注的朋友,可以回顾前两篇文章: 基础应用开发 分布式应用开发 上篇文章总结了<深入实践Spring Boot>的第二部分,本篇文章总结第三部分,也是最后一部分.这部分主要讲解核心技术的 ...

  9. SpringBoot入门:新一代Java模板引擎Thymeleaf(实践)

    菜鸟教程:http://www.runoob.com/ http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js http://apps.b ...

  10. Spring Security入门(1-12)Spring Security 的过滤器机制

    Servlet过滤器被用来拦截用户请求来进行请求之前或之后的处理,或者干脆重定向这个请求,这取决于servlet过滤器的功能. Servlet过滤器处理之后的目标servlet是 MVC 分发web ...