Description

风见幽香非常喜欢玩一个叫做osu!的游戏,其中她最喜欢玩的模式就是接水果。
由于她已经DT FC了The big black, 她觉得这个游戏太简单了,于是发明了一个更加难的版本。首先有一个地图,是一棵由\(n\)个顶点、\(n-1\)条边组成的树。这颗树上有\(P\)个盘子,每个盘子实际上是一条路径,并且每个盘子还有一个权值。第\(i\)个盘子就是顶点\(a_{i}\)到顶点\(b_{i}\)的路径(由于是树,所以从\(a_{i}\)到\(b_{i}\)的路径是唯一的),权值为\(c_{i}\)。接下来依次会有\(Q\)个水果掉下来,每个水果本质上也是一条路径,第\(i\)个水果是从顶点\(u_{i}\)到顶点\(v_{i}\)的路径。幽香每次需要选择一个盘子去接当前的水果:一个盘子能接住一个水果,当且仅当盘子的路径是水果的路径的子路径。这里规定:从\(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 \le c \le 10^{9},a \neq b\)。
接下来\(Q\)行,每行三个数\(u,v,k\),表示路径为\(u\)到\(v\)的水果,其中\(u \neq 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 \le 40000\)。

整体二分。对于区间\(l \sim r\),二分值域\(mid\),将\(\le mid\)的盘子加入,每个水果的\(k\)与其路径上存在的盘子数进行比较,若多了该询问往左区间\(l \sim mid\)递归,否则往右区间\(mid+1 \sim r\)递归。
现在的问题就是如何判定每个水果的\(k\)与其路径上存在的盘子数的大小关系。考虑每个盘子,覆盖的路径为\(a_{i}\)到\(b_{i}\)(\(dep_{a_{i}} < dep_{b_{i}}\)),那么这个盘子所贡献的水果只有可能两种情况:
\(1.b_{i}\)在\(a_{i}\)的子树内,那么水果的两个端点\(u,v\)必须一个\(b_{i}\)的子树内,一个在\(a_{i}\)的子树外(可以包括\(a_{i}\))。
\(2.\)否则,两个点必须一个在\(a_{i}\)的子树内,一个在\(b_{i}\)的子树内。
看到有子树的东西,马上想到dfs序。由于这个dfs序是一段连续的区间,所以我们可以将盘子根据dfs序抽象成为矩形(情况一上两个不相交的矩形,情况二是一个矩形),将水果抽象成为一个点,每次检验即询问点被多少矩形所覆盖。扫描线+树状数组即可解决。
注意:矩形必须保证\(x\)坐标小于\(y\)坐标。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
using namespace std;#define maxn (40010)
int N,P,Q,side[maxn],next[maxn*2],toit[maxn*2],dep[maxn],tree[maxn];
int L[maxn],R[maxn],ans[maxn],f[maxn][20],Ts,cnt,tot,have[maxn],sum[maxn];
struct SCAN
{int X,Y1,Y2,sign,be;friend inline bool operator <(const SCAN &a,const SCAN &b) { return a.X != b.X?a.X < b.X:a.sign<b.sign; }
}bac[8*maxn],save[maxn][4];inline int jump(int a,int step)
{for (int i = 0;step;step >>= 1,++i) if (step&1) a = f[a][i];return a;
}inline int lowbit(int a) { return a&-a; }
inline void modify(int a,int b) { for (;a <= N;a += lowbit(a)) tree[a] += b; }
inline int calc(int a) { int ret = 0; for (;a;a -= lowbit(a)) ret += tree[a]; return ret; }struct NODE
{int a,b,c,id;friend inline bool operator <(const NODE &x,const NODE &y) { return x.c < y.c; }inline void read(int i) { scanf("%d %d %d",&a,&b,&c); id = i; }inline void update() { if (L[a] > L[b]) swap(a,b); }inline void ins1() { bac[++tot] = (SCAN){L[a],L[b],L[b],0,id}; }inline void ins2() { for (int i = 0;i < have[id];++i) bac[++tot] = save[id][i]; }inline void change(){if (L[b] >= L[a]&&L[b] <= R[a]){int son = jump(b,dep[b]-dep[a]-1);if (L[son] > 1){save[id][have[id]++] = (SCAN){1,L[b],R[b],-1,id};save[id][have[id]++] = (SCAN){L[son]-1,L[b],R[b],1,id};}if (R[son] < N){save[id][have[id]++] = (SCAN){L[b],R[son]+1,N,-1,id};save[id][have[id]++] = (SCAN){R[b],R[son]+1,N,1,id};}}else{save[id][have[id]++] = (SCAN){L[a],L[b],R[b],-1,id};save[id][have[id]++] = (SCAN){R[a],L[b],R[b],1,id};}}
}path[maxn],query[maxn],tmp[maxn];inline void add(int a,int b) { next[++cnt] = side[a]; side[a] = cnt; toit[cnt] = b; }
inline void ins(int a,int b) { add(a,b); add(b,a); }inline void dfs(int now)
{L[now] = ++Ts;for (int i = 1;(1 << i) <= dep[now];++i) f[now][i] = f[f[now][i-1]][i-1];for (int i = side[now];i;i = next[i])if (toit[i] != f[now][0])f[toit[i]][0] = now,dep[toit[i]] = dep[now]+1,dfs(toit[i]);R[now] = Ts;
}inline void census(int ql,int qr,int pl,int pr,int &ll,int &rr)
{tot = 0;for (int i = pl;i <= pr;++i) path[i].ins2();for (int i = ql;i <= qr;++i) query[i].ins1();sort(bac+1,bac+tot+1);for (int i = 1;i <= tot;++i){if (!bac[i].sign) sum[bac[i].be] = calc(bac[i].Y1);else modify(bac[i].Y1,-bac[i].sign),modify(bac[i].Y2+1,bac[i].sign);}for (int i = ql;i <= qr;++i){if (sum[query[i].id] >= query[i].c) tmp[++ll] = query[i];else query[i].c -= sum[query[i].id],tmp[--rr] = query[i];sum[query[i].id] = 0;}for (int i = ql;i <= qr;++i) query[i] = tmp[i];for (int i = 1;i <= tot;++i)if (bac[i].sign) modify(bac[i].Y1,bac[i].sign),modify(bac[i].Y2+1,-bac[i].sign);
}inline void work(int ql,int qr,int pl,int pr)
{if (ql > qr) return;if (pl == pr){for (int i = ql;i <= qr;++i) ans[query[i].id] = path[pl].c;return;}int ll = ql-1,rr = qr+1,mid = (pl + pr)>>1;census(ql,qr,pl,mid,ll,rr);work(ql,ll,pl,mid); work(rr,qr,mid+1,pr);
}int main()
{freopen("fruit.in","r",stdin);freopen("fruit.out","w",stdout);scanf("%d %d %d",&N,&P,&Q);for (int i = 1,a,b;i < N;++i) scanf("%d %d",&a,&b),ins(a,b);dfs(1);for (int i = 1;i <= P;++i) path[i].read(i),path[i].update(),path[i].change();sort(path+1,path+P+1);for (int i = 1;i <= Q;++i) query[i].read(i),query[i].update();work(1,Q,1,P);for (int i = 1;i <= Q;++i) printf("%d\n",ans[i]);fclose(stdin); fclose(stdout);return 0;
}

转载于:https://www.cnblogs.com/mmlz/p/4448719.html

BZOJ 4009 接水果相关推荐

  1. bzoj 4009 接水果 整体二分

    Description 先给出一些盘子, 用路径x-y表示, 有权值 再有Q个询问, 表示水果, 用路径x-y表示 如果盘子是水果的子路径, 可以接住 对于每个水果, 输出可以接住它的盘子的第k小权 ...

  2. bzoj 4009: [HNOI2015]接水果 整体二分+k-d tree

    Description 风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果. 由于她已经DT FC 了The big black, 她觉得这个游戏太简单了,于是发明了一个更 加 ...

  3. BZOJ 4009 HNOI2015 接水果 树套树

    题目大意:给定一棵树和m<script type="math/tex" id="MathJax-Element-32">m</script&g ...

  4. heheda练数据结构

    联赛结束,自己的码力已经下降了不知多少个档次,再加上最近空闲时间比较多,我就开启了这个可以说最费时间的专题. //话说我未完成的数论专题还会继续的. 最近看了以下知识点: 线段树套线段树 线段树套平衡 ...

  5. BZOJ.1558.[JSOI2009]等差数列(线段树 差分)

    BZOJ 洛谷 首先可以把原序列\(A_i\)转化成差分序列\(B_i\)去做. 这样对于区间加一个等差数列\((l,r,a_0,d)\),就可以转化为\(B_{l-1}\)+=\(a_0\),\(B ...

  6. S-T平面图中利用最短路求最小割(BZOJ 1001)

    BZOJ 1001: [BeiJing2006]狼抓兔子 最小割 题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1001 现在小朋友们最喜欢 ...

  7. 数据库实验:数据库和表、查询、视图与安全性、存储过程及游标、触发器、综合实验-水果商店进阶

    数据库实验:数据库和表.查询.视图与安全性.存储过程及游标.触发器.综合实验-水果商店进阶 实验一.数据库和表 源码1: 源码2: 小结 实验二.查询 源码 小结 实验三.视图.安全性 源码: 小结 ...

  8. 【JAVA小游戏+水果售卖系统】基于GUI界面编程的水果“人生”模拟系统

    [JAVA]基于GUI界面编程的水果"人生"模拟系统 一.系统主要功能及简介 二.系统体系结构 三.系统设计技术 四.编码说明 五.效果展示 一.系统主要功能及简介 该系统以JAV ...

  9. BZOJ 1124: [POI2008]枪战Maf(构造 + 贪心)

    题意 有 \(n\) 个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺序开枪,且任意时刻只有一个人开枪. 因此,对于不同的开枪顺序,最后死的人也不同. 问最 ...

最新文章

  1. 搭建多语言外文网站需要注意三个细节问题
  2. Java教程分享:使用Spring框架能带来哪些好处?
  3. centos安装时卡住不动_转子流量计转子或指针停在某一位置不动的原因及处理方法...
  4. 英语 语义分割_英语关系分句的翻译技巧
  5. 桌面虚拟化之运维支持
  6. ARP-Address Resolution Protocol-地址解析协议
  7. spring学习(41):属性注入
  8. 怎么样让用户认为产品更有价值?让他们DIY吧!
  9. android 方法统计,Android 利用编译时 注入 统计App内所有方法执行时常,分析ANR
  10. windows 安装 mongodb
  11. CentOS5.8分区与文件系统
  12. 运维工程师面试题(1)
  13. Java中涉及到金钱计算方法
  14. java计算机毕业设计校园订餐系统源码+系统+数据库+lw文档+mybatis+运行部署
  15. Jquery UI中 Dialog对象的作用及常用属性
  16. 【光学】(一) 光阑、光瞳
  17. fancyhdr页眉页脚设计史上最全代码
  18. 浅谈Nginx转发匹配规则
  19. python写小说阅读器_手把手教你用Python制作简易小说阅读器
  20. 3D MAX脚本教程1

热门文章

  1. 金山android 杀毒软件,金山手机卫士
  2. java map 输入 查询 修改_Mybatis增删改查mapper文件写法详解
  3. inum在linux中含义,linux
  4. pythonclass全局变量_Python-多处理全局变量更新未返回给父级
  5. 永州科技学院有计算机专业吗,永州科技学院有哪些专业
  6. python基础知识整理 第七节:单例设计模式、异常、模块、包、制作模块、文件
  7. 【camera】自动驾驶感知系统实现(车道线检测和拟合、目标检测与跟踪、道路可行驶区域分割、深度估计、图像视野到BEV空间映射、像平面到地平面映射)
  8. ROS、realsense开发常用命令汇总
  9. Makefile中的几个调试方法
  10. webstorm设置git pull快捷键Ctrl+Shift+P