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. Java字符串的split(String str)方法空串的问题

    String strs[] = "SS1BB2CC3".split("\\D+"); public static String Test(){ Date d = ...

  2. git(一)快速入门

    1.设置用户名 git config --global user.name '你的用户名' ​ 2.设置用户名邮箱 git config --global user.email '你的邮箱' ​ 3. ...

  3. Django-rest-framework源码分析----认证

    一.前言 1.1.安装 两种方式: github pip直接安装 pip install django-rest-framework 1.2.需要先了解的一些知识 理解下面两个知识点非常重要,djan ...

  4. 利用Node的chokidar 监听文件改变的文件。

    最近维护一个项目.每次改完东西,都要上传到服务器.然后有时候就忘记一些东西,于是就想有没有可以方法能监听文件的改变.然后我再利用程序把更改的文件一键上传到服务器. 于是就找到了nodejs 的chok ...

  5. Python设计TFTP客户端

    #coding=utf-8 from socket import * from threading import Thread import struct def recvData(fileName, ...

  6. python+flask 分分钟完美解析阿里云日志

    拿到了自己阿里云服务器的日志,对其需要进行处理. class Read_Rizhi: def __init__(self,filename): self.filename=filename def o ...

  7. Spring-Boot导入配置文件与取值

    前言: springboot简化了大量配置文件,但是必要时还是需要导入配置文件的,比如dubbo,此处简记之. 正文: 所有的配置文件引入都是使用注解在类上进行引入的,常用的有两种注解@Propert ...

  8. spring9——AOP之AspectJ对AOP的实现

    从上述的实验中可以看出BeanNameAutoProxyCreator对于AOP的实现已经和完美了,但是还有两点不足之处: 1,对于切面的实现比较麻烦,既不同类型的通知切面要实现不同的接口,而且一个切 ...

  9. System Rules 更好的测试

    1:编写测试事例时候,我们要从控制台拿到数据与断言进行对比,通常要编写jdk 标准输出的屏蔽控制器.文章标题的包,能够更好的为我们进行工作. package demo2; import static ...

  10. Docker学习(1)安装

    1. Docker简介 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱 ...