【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\)在一条链上,那么水果的两点就要在这条链之外 不在的话,水果的两点就分别在盘子的两点的子树中 记录 ...
随机推荐
- Tableau10.4中智能显示点击后消失的解决方案
如果你的电脑是Win10,并且是高分屏,可能会出现和我一样的问题,就点击智能显示后,发现找不到了. 那么解决方案就是: 这样就能找到智能显示了.
- 通过iframe标签绕过csp
iframe.php代码如下: allow-popups开启时,window.open就可以打开新的窗口. 看csp规则,默认是在当前域内,如果这是一个ctf题的话,就很简单了,window.loca ...
- pwnhub_WTP攻击思路--self-xss高级利用
1.self-xss+302跳转构造csrf的利用: 1.login.php 存在跳转2.http://54.223.108.205:23333/login.php?redirecturl=//vps ...
- controller中的路径明明书写正确,浏览器中访问的url也拼接正确,但报404
Bug:controller中的路径明明书写正确,浏览器中访问的url也拼接正确,但报404 原因一:由于路由地址对应的处理方法存在同名而造成的,此时应该检查controller的方法们,看看有没有同 ...
- 【vue】父向子组件传参、子组件向父传参
1.父向子组件传参 App.vue为父,引入componetA组件之后,则可以在App.vue中使用标签(注意驼峰写法要改成componet-a写法,因为html对大小写不敏感,componenta与 ...
- linux下搭建禅道项目管理系统
1.禅道下载: #官网:http://www.zentao.net/article-browse-1067.html [root@localhost ~]# wget ...
- PAT——1047. 编程团体赛
编程团体赛的规则为:每个参赛队由若干队员组成:所有队员独立比赛:参赛队的成绩为所有队员的成绩和:成绩最高的队获胜. 现给定所有队员的比赛成绩,请你编写程序找出冠军队. 输入格式: 输入第一行给出一个正 ...
- Java中的集合框架-Collection(一)
一,Collection接口 在日常的开发工作中,我们经常使用数组,但是数组是有很多的局限性的,比如:数组大小固定后不可修改,只能存储基本类型的值等等. 基于数组的这些局限性,Java框架就产生了用于 ...
- Field userService in com.wuji.controller.UserController required a bean of type 'com.wuji.service.UserService' that could not be found
Field userService in com.wuji.controller.UserController required a bean of type 'com.wuji.service.Us ...
- 搭建Java的运行和开发环境
Java最大的优势就是跨平台,即编译一次,就能在linux.windows和mac等平台运行,无需再次编译.而典型的C和C++ 则是源代码跨平台,需要根据不同平台的编译规范来进行编译. Java如何跨 ...