题目

【题目描述】

风见幽香非常喜欢玩一个叫做 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$ 小的那个盘子,每个盘子可重复使用(没有使用次数的上限:一个盘子接完一个水果后,后面还可继续接其他水果,只要它是水果路径的子路径)。幽香认为这个游戏很难,你能轻松解决给她看吗?

【输入格式】

第一行三个数 $n$ 和 $P$ 和 $Q$,表示树的大小和盘子的个数和水果的个数。

接下来 $n-1$ 行,每行两个数 $a$、$b$,表示树上的 $a$ 和 $b$ 之间有一条边。树中顶点按 $1$ 到 $n$ 标号。 接下来 $P$ 行,每行三个数 $a$、$b$、$c$,表示路径为 $a$ 到 $b$、权值为 $c$ 的盘子,其中 $0 \leq c \leq 10^9, \ a \neq b$。
 
接下来 $Q$ 行,每行三个数 $u$、$v$、$k$,表示路径为 $u$ 到 $v$ 的水果,其中 $u$ 不等于 $v$,你需要选择第 $k$ 小的盘子,第 $k$ 小一定存在。

【输出格式】

对于每个果子,输出一行表示选择的盘子的权值。

【样例输入】

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

【样例输出】

442139372
333042360
442139372
283254485
283254485
217394434
217394434
217394434
217394434
217394434

【数据范围与提示】

对于所有数据,$N,P,Q \leq 40000$。

题解

考虑一个盘子 $ u,v $ 能接到的水果的范围,那么水果的 $ s,t $ 必须分别属于盘子两个的两个子树,问题即转化成 $ s,t $ 属于的第 $k$ 大的盘子

因为一个子树在 dfs 序上是一个区间,一个盘子就是两个区间的包含关系,那么映射到坐标系上盘子就成了一个矩形,水果就成了一个点,问题变成覆盖某一个点的第 $k$ 大的矩形

考虑如何解决,整体二分矩形,判断覆盖个数是否大于,然后左右递归即可

至于判断,类似扫描线的思想,将矩形按一维排序,另一维区间用数据结构(树状数组)维护,单点查询即可

如果水果 $ u,v $ 的 lca 为 $ u $ 或 $ v $ 时,需要特判一下

时间效率:$ O(n \log^2 n) $

代码

 1 #include<bits/stdc++.h>
 2 const int N=8e4+10;
 3 using namespace std;
 4 int n,m,q,tot,fa[N][18],dfn[N],tim,last[N],dep[N],ans[N],sum[N],head[N],cnt;
 5 struct edge{int to,nex;}e[N<<1];
 6 struct Plate{int x1,x2,y1,y2,v;}pla[N];
 7 struct node{int x,y1,y2,v,id;}eve[N];
 8 struct fruit{int x,y,k,id;}fru[N],s1[N],s2[N];
 9 bool cmp(Plate a,Plate b){return a.v<b.v;}
10 bool cmp1(node a,node b){return a.x==b.x?a.id<b.id:a.x<b.x;}
11 void add(int s,int t){e[++cnt]=(edge){t,head[s]},head[s]=cnt;}
12
13 class Bit{
14 public:
15     int val[N];
16     void modify(int l,int r,int v){
17         for (int i=l;i<=n;i+=(i&(-i))) val[i]+=v;
18         for (int i=r+1;i<=n;i+=(i&(-i))) val[i]-=v;
19     }
20     int query(int x){int res=0;for (;x;x-=(x&(-x))) res+=val[x];return res;}
21 }T;
22
23 void dfs(int x){
24     dfn[x]=++tim;
25     for (int i=0;fa[x][i];i++) fa[x][i+1]=fa[fa[x][i]][i];
26     for (int k=head[x],v;k;k=e[k].nex)
27         if ((v=e[k].to)!=fa[x][0])
28             fa[v][0]=x,dep[v]=dep[x]+1,dfs(v);
29     last[x]=tim;
30 }
31 int jump(int a,int h){for (int i=16;h;i--) if (h>=(1<<i)) h-=(1<<i),a=fa[a][i];return a;}
32 int lca(int a,int b){
33     if (dep[a]<dep[b]) swap(a,b);
34     a=jump(a,dep[a]-dep[b]);
35     if (a==b) return a;
36     for (int i=16;i>=0;i--) if (fa[a][i]!=fa[b][i]) a=fa[a][i],b=fa[b][i];
37     return fa[a][0];
38 }
39
40 void solve(int l,int r,int st,int ed){
41     if (st>ed) return;
42     if (l==r){
43         for (int i=st;i<=ed;i++) ans[fru[i].id]=pla[l].v;
44         return;
45     }
46     int mid=(l+r)>>1,siz=0;
47     for (int i=l;i<=mid;i++){
48         eve[++siz]=(node){pla[i].x1,pla[i].y1,pla[i].y2,1,0};
49         eve[++siz]=(node){pla[i].x2,pla[i].y1,pla[i].y2,-1,n+1};
50     }
51     for (int i=st;i<=ed;i++) eve[++siz]=(node){fru[i].x,fru[i].y,0,0,i};
52     sort(eve+1,eve+1+siz,cmp1);
53     for (int i=1;i<=siz;i++)
54         if (st<=eve[i].id&&eve[i].id<=ed) sum[eve[i].id]=T.query(eve[i].y1);
55         else T.modify(eve[i].y1,eve[i].y2,eve[i].v);
56     int a=0,b=0;
57     for (int i=st;i<=ed;i++) {
58         if (sum[i]>=fru[i].k) s1[++a]=fru[i];
59         else s2[++b]=(fruit){fru[i].x,fru[i].y,fru[i].k-sum[i],fru[i].id};
60     }
61     for (int i=st;i<=st+a-1;i++) fru[i]=s1[i-st+1];
62     for (int i=st+a;i<=ed;i++) fru[i]=s2[i-st-a+1];
63     solve(l,mid,st,st+a-1),solve(mid+1,r,st+a,ed);
64 }
65
66 int main(){
67     scanf("%d%d%d",&n,&m,&q);
68     for (int i=1,a,b;i<n;i++) scanf("%d%d",&a,&b),add(a,b),add(b,a);
69     dfs(1);
70     for (int i=1,a,b,c,u;i<=m;i++){
71         scanf("%d%d%d",&a,&b,&c);u=lca(a,b);
72         if (dfn[a]>dfn[b]) swap(a,b);
73         if (u!=a) pla[++tot]=(Plate){dfn[a],last[a],dfn[b],last[b],c};
74         else{
75             int w=jump(b,dep[b]-dep[a]-1);
76             pla[++tot]=(Plate){1,dfn[w]-1,dfn[b],last[b],c};
77             if (last[w]<n) pla[++tot]=(Plate){dfn[b],last[b],last[w]+1,n,c};
78         }
79     }
80     sort(pla+1,pla+1+tot,cmp);
81     for (int i=1,a,b,k;i<=q;i++){
82         scanf("%d%d%d",&a,&b,&k);
83         if (dfn[a]>dfn[b]) swap(a,b);
84         fru[i]=(fruit){dfn[a],dfn[b],k,i};
85     }
86     solve(1,tot,1,q);
87     for (int i=1;i<=q;i++) printf("%d\n",ans[i]);
88     return 0;
89 }

View Code

转载于:https://www.cnblogs.com/chmwt/p/10632461.html

接水果(fruit)——整体二分+扫描线相关推荐

  1. 【HNOI2015】接水果【整体二分】【DFS序】【双区间转矩形】【扫描线】【树状数组】

    传送门 题意:给定一个nnn个点的树,定义一个"盘子"为一个给定权值的路径,一个"水果"为一条路径,一个盘子可以接到水果当且仅当盘子的路径是水果的子路径.给出所 ...

  2. P3242 [HNOI2015] 接水果(整体二分、扫描线)

    P3242 [HNOI2015] 接水果 给定一棵树,定义给定了ppp个盘子,每个盘子是树上u,vu, vu,v两点的路径,且盘子有权值,定义水果,水果也是树上u,vu, vu,v两点间的路径. 有q ...

  3. P3242 [HNOI2015] 接水果(整体二分、扫描线、dfs序)

    解析 一道有点毒瘤的题 也是一道感觉真的可以出现在考场上的很综合的题 做的还可以 除了一开始把盘子和水果看反白写了各树套树之外 为什么盘子是水果的子路径啊 由于是做专题爬过来的多次询问区间第k小,想到 ...

  4. bzoj4009: [HNOI2015]接水果(整体二分)

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

  5. [XSY3112] 接水果(树上包含路径,整体二分,扫描线)

    传送门 给出一棵nnn个点的树.接下来给出PPP条树上路径ai→bia_i\to b_iai​→bi​,及其权值cic_ici​.最后有QQQ个询问,每个询问给出一条树上路径ui→viu_i\to v ...

  6. 【bzoj4009】[HNOI2015]接水果 DFS序+树上倍增+整体二分+树状数组

    题目描述 给出一棵n个点的树,给定m条路径,每条路径有一个权值.q次询问求一个路径包含的所有给定路径中权值第k小的. 输入 第一行三个数 n和P 和Q,表示树的大小和盘子的个数和水果的个数. 接下来n ...

  7. [HNOI2015] 接水果(倍增 + 整体二分)

    problem luogu-P3242 solution 本题的难点在于如何判定路径之间是否覆盖. 这里我们尝试树常见的 dfs\text{dfs}dfs 序. 考虑 x−yx-yx−y 路径如果要覆 ...

  8. bzoj 4009 接水果 整体二分

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

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

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

  10. 接水果(fruit)

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

最新文章

  1. Day 11: AeroGear 推送服务器:使应用的通知推送变得简单
  2. 在 Linux 下使用 水星MW150cus (RTL8188CUS芯片)无线网卡
  3. python数据整理 高一_关于Python爬虫的最全知识梳理,项目经理花了三天总结出来的经验...
  4. python的界面文字翻译_一个把网站全英文转成中文的方法,让你轻松看懂python官网...
  5. python中ijust函数_Python基础
  6. Linux 下的进程间通信:管道、消息队列、共享文件、共享内存
  7. 初学JAVA随记——代码练习(二元一次方程)
  8. 自定义 Dialog --- 仿照微信删除联系人界面
  9. TCP/IP协议栈详解
  10. slk文件转换器安卓版_CoolUtils Total Excel Converter下载
  11. 数学建模——更新1——excel箱线图
  12. linux系统编译Q,Linux下安装qBittorrent,开启24小时挂机BT下载
  13. SPSS如何验证是否符合正态分布
  14. GIS就业参考系列之方向篇——条条大道通罗马
  15. linux执行历史命令用哪个键,Linux中如何使用history命令即历史命令
  16. SCOI2018滚粗记
  17. 快应用上架时,你最关心的问题都在这里!
  18. 如何编写测试用例及用例的意义
  19. html canvas自适应屏幕,Unity canvas 和 canvas元素自适应全屏
  20. Java小农养成记第四十天

热门文章

  1. /usr/include/X11/Shell.h:51:26: 致命错误:X11/SM/SMlib.h:没有那个文件或目录
  2. OpenCV交叉编译ARM版本
  3. Android中sendMessageAtTime()的用法
  4. 管理感悟:主管加班,员工才会加班
  5. oracle 11.2.0.4 make 报错,linux7安装oracle11.2.0.4RAC注意事项
  6. 手把手分析 mfc 程序创建 代码执行流程
  7. 关于mysql数据库的说法错误的是_MYSQL数据库2013-2014学年考试试卷
  8. l4d2服务器修改武器伤害,辐射4武器伤害及护甲修改攻略
  9. java的gui的design模式怎么打开_手机越用越卡怎么办?打开这五个隐藏按钮,1分钟解决卡顿问题...
  10. mysql 并发_MySQL多版本并发控制机制(MVCC)源码浅析