【LG3242】 [HNOI2015]接水果
题面
题解
20pts
对于\(n,P,Q\leq 3000\),暴力判断每条路径的包含关系然后排序\(kth\)即可,复杂度\(O(PQ\log P)\)
另30pts
原树为一条链。
发现对于每个盘子,也就是区间\(x,y\),那么对于包含这个区间的水果\(u,v\),要满足\(u\leq x\leq y\leq v\)。
将水果和盘子放在二维平面上一维排序,一维用数据结构维护即可。
100pts
设对于一个点\(x\),我们\(dfs\)时第一次访问的时间为\(L_x\),回溯时时间为\(R_x\)。
那么我们下面讨论一下路径之间的包含关系:
对于路径\(u,v\)(\(dep_u<dep_v\)),包含它的路径\(x,y\)有以下情况:
1.\(lca_{u,v}\neq u\),显然有\(L_u\leq L_x\leq R_u\),\(L_v\leq L_y\leq R_v\),
可以看作点\((L_x,L_y)\)包含在矩形\(\{(L_u,L_v),(R_u,R_v)\}\)中。
2.\(lca_{u,v}= u\),设\(w\)为路径\(u,v\)中\(u\)的儿子,那么显然有一个点在\(v\)的子树内,
另一个点在除了\(w\)子树的其他地方,
写成上面那样的关系,就是点\((L_x,L_y)\)在矩形\(\{(1,L_v),(L_w-1,R_v)\}\cup \{(L_v,R_w+1),(R_v,n)\}\)中。
然后对于这个东西,整体二分+扫描线,看有几个在\((L_x,L_y)\)上的权值在\(mid\leq\),按照整体二分的套路搞即可。
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
inline int gi() {
register int data = 0, w = 1;
register char ch = 0;
while (!isdigit(ch) && ch != '-') ch = getchar();
if (ch == '-') w = -1, ch = getchar();
while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
return w * data;
}
const int MAX_N = 4e4 + 5;
struct Graph { int to, next; } e[MAX_N << 1]; int fir[MAX_N], e_cnt;
void clearGraph() { memset(fir, -1, sizeof(fir)); e_cnt = 0; }
void Add_Edge(int u, int v) { e[e_cnt] = (Graph){v, fir[u]}; fir[u] = e_cnt++; }
int N, P, Q;
int dep[MAX_N], L[MAX_N], R[MAX_N], tim;
int pa[17][MAX_N];
void dfs(int x, int fa) {
dep[x] = dep[fa] + 1, L[x] = ++tim;
for (int i = 0; i < 16; i++) pa[i + 1][x] = pa[i][pa[i][x]];
for (int i = fir[x]; ~i; i = e[i].next) {
int v = e[i].to; if (v == fa) continue;
pa[0][v] = x, dfs(v, x);
}
R[x] = tim;
}
int LCA(int u, int v) {
if (dep[u] < dep[v]) swap(u, v);
for (int i = 16; i >= 0; i--)
if ((1 << i) <= dep[u] - dep[v]) u = pa[i][u];
if (u == v) return u;
for (int i = 16; i >= 0; i--)
if (pa[i][u] != pa[i][v]) u = pa[i][u], v = pa[i][v];
return pa[0][u];
}
int Jump(int x, int num) {
for (int i = 16; i >= 0; i--) if ((num >> i) & 1) x = pa[i][x];
return x;
}
int q_cnt, p_cnt;
struct Line { int x, _y, y, op, val; } p[MAX_N << 2], lp[MAX_N << 2], rp[MAX_N << 2];
bool operator < (const Line &l, const Line &r) { return l.x < r.x; }
struct Query { int x, y, k, id; } q[MAX_N], lq[MAX_N], rq[MAX_N];
bool operator < (const Query &l, const Query &r) { return l.x < r.x; }
inline int lb(int x) { return x & -x; }
int ans[MAX_N], c[MAX_N];
void add(int x, int v) { while (x <= N) c[x] += v, x += lb(x); }
int sum(int x) { int res = 0; while (x > 0) res += c[x], x -= lb(x); return res; }
int h[MAX_N], cnt = 0;
void Div(int lval, int rval, int sp, int tp, int sq, int tq) {
if (sp > tp || sq > tq) return ;
if (lval == rval) {
for (int i = sq; i <= tq; i++) ans[q[i].id] = h[lval];
return ;
}
int mid = (lval + rval) >> 1;
int ql = 0, qr = 0, pl = 0, pr = 0, j = sp;
for (int i = sq; i <= tq; i++) {
for ( ; j <= tp && p[j].x <= q[i].x; j++) {
if (p[j].val > h[mid]) rp[++pr] = p[j];
else add(p[j]._y, p[j].op), add(p[j].y + 1, -p[j].op), lp[++pl] = p[j];
}
int tmp = sum(q[i].y);
if (q[i].k > tmp) q[i].k -= tmp, rq[++qr] = q[i];
else lq[++ql] = q[i];
}
for ( ; j <= tp; j++)
if (p[j].val > h[mid]) rp[++pr] = p[j];
else add(p[j]._y, p[j].op), add(p[j].y + 1, -p[j].op), lp[++pl] = p[j];
for (int i = 1; i <= pl; i++) add(lp[i]._y, -lp[i].op), add(lp[i].y + 1, lp[i].op);
for (int i = 1; i <= pl; i++) p[i + sp - 1] = lp[i];
for (int i = 1; i <= pr; i++) p[sp + pl - 1 + i] = rp[i];
for (int i = 1; i <= ql; i++) q[i + sq - 1] = lq[i];
for (int i = 1; i <= qr; i++) q[sq + ql - 1 + i] = rq[i];
Div(lval, mid, sp, sp + pl - 1, sq, sq + ql - 1);
Div(mid + 1, rval, sp + pl, tp, sq + ql, tq);
}
int main () {
#ifndef ONLINE_JUDGE
freopen("cpp.in", "r", stdin);
#endif
clearGraph();
N = gi(), P = gi(), Q = gi();
for (int i = 1; i < N; i++) {
int u = gi(), v = gi();
Add_Edge(u, v), Add_Edge(v, u);
}
dfs(1, 0);
for (int i = 1; i <= P; i++) {
int u = gi(), v = gi(); h[i] = gi();
if (L[u] > L[v]) swap(u, v);
int lca = LCA(u, v);
if (lca == u) {
int z = Jump(v, dep[v] - dep[u] - 1);
p[++p_cnt] = (Line){1, L[v], R[v], 1, h[i]};
p[++p_cnt] = (Line){L[z], L[v], R[v], -1, h[i]};
if (R[z] < N) {
p[++p_cnt] = (Line){L[v], R[z] + 1, N, 1, h[i]};
p[++p_cnt] = (Line){R[v] + 1, R[z] + 1, N, -1, h[i]};
}
} else {
p[++p_cnt] = (Line){L[u], L[v], R[v], 1, h[i]};
p[++p_cnt] = (Line){R[u] + 1, L[v], R[v], -1, h[i]};
}
}
sort(&p[1], &p[p_cnt + 1]);
sort(&h[1], &h[P + 1]); cnt = unique(&h[1], &h[P + 1]) - h - 1;
while (Q--) {
int u = gi(), v = gi(), k = gi();
if (L[u] > L[v]) swap(u, v);
q[++q_cnt] = (Query){L[u], L[v], k, q_cnt};
}
sort(&q[1], &q[q_cnt + 1]);
Div(1, cnt, 1, p_cnt, 1, q_cnt);
for (int i = 1; i <= q_cnt; i++) printf("%d\n", ans[i]);
return 0;
}
【LG3242】 [HNOI2015]接水果的更多相关文章
- BZOJ4009: [HNOI2015]接水果
4009: [HNOI2015]接水果 Description 风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果. 由于她已经DT FC 了The big black, 她 ...
- BZOJ 4009: [HNOI2015]接水果
4009: [HNOI2015]接水果 Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 636 Solved: 300[Submit][Status] ...
- [BZOJ4009][HNOI2015]接水果(整体二分)
[HNOI2015]接水果 时间限制:60s 空间限制:512MB 题目描述 风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果. 由于她已经DT FC 了The b ...
- 洛谷 P3242 [HNOI2015]接水果 解题报告
P3242 [HNOI2015]接水果 题目描述 风见幽香非常喜欢玩一个叫做 \(osu!\) 的游戏,其中她最喜欢玩的模式就是接水果.由于她已经\(DT\) \(FC\) 了\(\tt{The\ b ...
- [洛谷P3242] [HNOI2015]接水果
洛谷题目链接:[HNOI2015]接水果 题目描述 风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果.由于她已经DT FC 了The big black, 她觉得这个游戏太简 ...
- 【BZOJ4009】[HNOI2015]接水果 DFS序+整体二分+扫描线+树状数组
[BZOJ4009][HNOI2015]接水果 Description 风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果.由于她已经DT FC 了The big black, ...
- [HNOI2015]接水果[整体二分]
[HNOI2015]接水果 给出一个树上路径集合\(S\) 多次询问\(x,y\)中的\(k\)小值 如果你问我数列上那么我会 树上的话 树上差分了吧直接?- 令 \(st_x<st_y\) 1 ...
- [Luogu3242][HNOI2015]接水果
Luogu 我今天做两道整体二分结果全都是BZOJ权限题??? sol 我们抓住"盘子的路径是水果的路径的子路径"这个条件. 考虑每一个盘子路径\((u,v)\),讨论它可以作为哪 ...
- Luogu3242:[HNOI2015]接水果
题面 Luogu3242 Sol 考虑每个盘子怎样才能接到一个水果 分两种情况: 盘子的\(x, y\)在一条链上,那么水果的两点就要在这条链之外 不在的话,水果的两点就分别在盘子的两点的子树中 记录 ...
随机推荐
- HDU 4652 Dice
嘟嘟嘟 题目大意就是对于一个m面的骰子,回答这么两个问题: 1.求连续扔n次都是同一数字的期望次数. 2.求连续扔n次每一次数字都不相同的期望次数. 对于期望dp特别菜的我来说,这道题已经算是很难了. ...
- [转]浅谈利用SQLite存储离散瓦片的思路和实现方法
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 在多个项目中涉及到互联网地图的内网显示,通过自制工具完成了互联 ...
- Genymotion集成到Eclipse
在Eclipse中使用Genymotion Google的ADT中自带的模拟器速度太慢,可以使用Genymotion代替.关于Genymotion的安装方法,可以直接访问官网,需要注册账号,因为创建模 ...
- HDU 1711 Number Sequence (KMP简单题)
Number Sequence Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- nRF5 SDK for Mesh(八) Exploring Mesh APIs using light switch example,使用 灯开关 案例探索BLE mesh 的APIS
Exploring Mesh APIs using light switch example The light switch example is meant to showcase the API ...
- javascript之promise
js语言的执行环境是"单线程",即一次只能执行一个任务,如果有多个任务的话,就需要排队,只有前面的一个任务执行结束了,再执行后面的一个任务.于是异步执行就变得非常重要,异步执行之后 ...
- iOS12适配及问题记录,Debug正常使用,Release数据为nil的报错
Debug模式数据一切正常,打包出去的ipa,Release模式下数据为nil的错误,经排查,buiding中的Optimization Level, Release设为None,解决问题. IOS1 ...
- python-基础小游戏,人在 江湖飘,哪能不挨刀,我几刀砍死你
#人在 江湖飘,哪能不挨刀,我几刀砍死你 #规则:5赢4. 4赢3 .3赢2. 2赢1 . 1赢5 #提示:绝对值函数abs #假设:老王和老李 import random import time p ...
- java8 新特性 Stream流 分组 排序 过滤 多条件去重
private static List<User> list = new ArrayList<User>(); public static void main(String[] ...
- 腾讯云的对象存储COS
什么是对象存储COS Clound Object Storage,COS,专门为企业和开发者们提供能够存储海量的分布式存储服务,用户可以随时通过互联网对大量数据进行批量存储和处理,在任意位置存储和检索 ...