题目

【题目描述】

风见幽香非常喜欢玩一个叫做 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) $

代码

 #include<bits/stdc++.h>
const int N=8e4+;
using namespace std;
int n,m,q,tot,fa[N][],dfn[N],tim,last[N],dep[N],ans[N],sum[N],head[N],cnt;
struct edge{int to,nex;}e[N<<];
struct Plate{int x1,x2,y1,y2,v;}pla[N];
struct node{int x,y1,y2,v,id;}eve[N];
struct fruit{int x,y,k,id;}fru[N],s1[N],s2[N];
bool cmp(Plate a,Plate b){return a.v<b.v;}
bool cmp1(node a,node b){return a.x==b.x?a.id<b.id:a.x<b.x;}
void add(int s,int t){e[++cnt]=(edge){t,head[s]},head[s]=cnt;} class Bit{
public:
int val[N];
void modify(int l,int r,int v){
for (int i=l;i<=n;i+=(i&(-i))) val[i]+=v;
for (int i=r+;i<=n;i+=(i&(-i))) val[i]-=v;
}
int query(int x){int res=;for (;x;x-=(x&(-x))) res+=val[x];return res;}
}T; void dfs(int x){
dfn[x]=++tim;
for (int i=;fa[x][i];i++) fa[x][i+]=fa[fa[x][i]][i];
for (int k=head[x],v;k;k=e[k].nex)
if ((v=e[k].to)!=fa[x][])
fa[v][]=x,dep[v]=dep[x]+,dfs(v);
last[x]=tim;
}
int jump(int a,int h){for (int i=;h;i--) if (h>=(<<i)) h-=(<<i),a=fa[a][i];return a;}
int lca(int a,int b){
if (dep[a]<dep[b]) swap(a,b);
a=jump(a,dep[a]-dep[b]);
if (a==b) return a;
for (int i=;i>=;i--) if (fa[a][i]!=fa[b][i]) a=fa[a][i],b=fa[b][i];
return fa[a][];
} void solve(int l,int r,int st,int ed){
if (st>ed) return;
if (l==r){
for (int i=st;i<=ed;i++) ans[fru[i].id]=pla[l].v;
return;
}
int mid=(l+r)>>,siz=;
for (int i=l;i<=mid;i++){
eve[++siz]=(node){pla[i].x1,pla[i].y1,pla[i].y2,,};
eve[++siz]=(node){pla[i].x2,pla[i].y1,pla[i].y2,-,n+};
}
for (int i=st;i<=ed;i++) eve[++siz]=(node){fru[i].x,fru[i].y,,,i};
sort(eve+,eve++siz,cmp1);
for (int i=;i<=siz;i++)
if (st<=eve[i].id&&eve[i].id<=ed) sum[eve[i].id]=T.query(eve[i].y1);
else T.modify(eve[i].y1,eve[i].y2,eve[i].v);
int a=,b=;
for (int i=st;i<=ed;i++) {
if (sum[i]>=fru[i].k) s1[++a]=fru[i];
else s2[++b]=(fruit){fru[i].x,fru[i].y,fru[i].k-sum[i],fru[i].id};
}
for (int i=st;i<=st+a-;i++) fru[i]=s1[i-st+];
for (int i=st+a;i<=ed;i++) fru[i]=s2[i-st-a+];
solve(l,mid,st,st+a-),solve(mid+,r,st+a,ed);
} int main(){
scanf("%d%d%d",&n,&m,&q);
for (int i=,a,b;i<n;i++) scanf("%d%d",&a,&b),add(a,b),add(b,a);
dfs();
for (int i=,a,b,c,u;i<=m;i++){
scanf("%d%d%d",&a,&b,&c);u=lca(a,b);
if (dfn[a]>dfn[b]) swap(a,b);
if (u!=a) pla[++tot]=(Plate){dfn[a],last[a],dfn[b],last[b],c};
else{
int w=jump(b,dep[b]-dep[a]-);
pla[++tot]=(Plate){,dfn[w]-,dfn[b],last[b],c};
if (last[w]<n) pla[++tot]=(Plate){dfn[b],last[b],last[w]+,n,c};
}
}
sort(pla+,pla++tot,cmp);
for (int i=,a,b,k;i<=q;i++){
scanf("%d%d%d",&a,&b,&k);
if (dfn[a]>dfn[b]) swap(a,b);
fru[i]=(fruit){dfn[a],dfn[b],k,i};
}
solve(,tot,,q);
for (int i=;i<=q;i++) printf("%d\n",ans[i]);
return ;
}

接水果(fruit)——整体二分+扫描线的更多相关文章

  1. 【BZOJ4009】接水果(整体二分,扫描线)

    [BZOJ4009]接水果(整体二分,扫描线) 题面 为什么这都是权限题???,洛谷真良心 题解 看到这道题,感觉就是主席树/整体二分之类的东西 (因为要求第\(k\)大) 但是,读完题目之后,我们发 ...

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

    LOJ BZOJ 洛谷 又是一个三OJ rank1!=w= \(Description\) (还是感觉,为啥非要出那种题目背景啊=-=直接说不好么) 给定一棵树和一个路径集合(每条路径有一个权值).\ ...

  3. 【BZOJ4009】[HNOI2015]接水果 DFS序+整体二分+扫描线+树状数组

    [BZOJ4009][HNOI2015]接水果 Description 风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果.由于她已经DT FC 了The big black, ...

  4. BZOJ 4009: [HNOI2015]接水果 (整体二分+扫描线 树状数组)

    整体二分+扫描线 树状数组 具体做法看这里a CODE #include <cctype> #include <cstdio> #include <cstring> ...

  5. [bzoj4009] [HNOI2015]接水果 整体二分+扫描线+dfs序+树状数组

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

  6. [HNOI2015][bzoj4009] 接水果 [整体二分+扫描线]

    题面 传送门 思路 本题其实有在线做法......但是太难写了,退而求其次写了离线 基本思路就是,考虑一个盘子以及它能接到的所有水果 可以发现,这个水果的端点一定在这个盘子两端的"子树&qu ...

  7. bzoj4009 [HNOI2015]接水果 整体二分+扫描线+树状数组+dfs序

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4009 题解 考虑怎样的情况就会有一个链覆盖另一个链. 设被覆盖的链为 \(a - b\),覆盖 ...

  8. 【BZOJ4009_洛谷3242】[HNOI2015] 接水果(整体二分)

    题目: 洛谷 3242 分析: 明确题意:在一棵树上给定若干权值为 \(w\) 的路径 \((u,v)\) (盘子),每次给定 \((a,b)\) (水果),询问所有满足 \((u,v)\) 被 \( ...

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

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

随机推荐

  1. Hibernate学习---第八节:继承关系的映射配置

    1.单表继承 (1).实体类,代码如下: package learn.hibernate.bean; import java.util.Date; /** * 持久化类设计 * 注意: * 持久化类通 ...

  2. 更新github上代码

    前面一篇已经实现首次上传代码到github了,本篇继续讲如何把本地更新的代码同步更新到github上 一.clone代码 1.把大神的代码clone到本地,或者clone自己github上的代码,使用 ...

  3. html实现摇一摇并震动

    今天收到了领导的通知,要APP和触屏完成摇一摇的功能,本来通过IOS调用原生还是蛮方便的,但想如果采用web前端的方式应该是实现不了的,马上就开始推脱了.可惜领导告知微信京东购物,不仅仅有摇一摇还有震 ...

  4. hdu-5637 Transform(位运算+bfs)

    题目链接: Transform Time Limit: 4000/2000 MS (Java/Others)     Memory Limit: 131072/131072 K (Java/Other ...

  5. bzoj 1441: Min 裴蜀定理

    题目: 给出\(n\)个数\((A_1, ... ,A_n)\)现求一组整数序列\((X_1, ... X_n)\)使得\(S=A_1*X_1+ ...+ A_n*X_n > 0\),且\(S\ ...

  6. openfire服务器开发环境搭建

    2017-07-26 更新:直接获取最新版源码,就不会报错了,而且可支持的插件多,老版本的openfire几乎没有可用的官方插件. 系统及软件环境: MAC OSX EI Capitan 10.11. ...

  7. 最常见的5个导致 RAC 实例崩溃的问题

    适用于: OracleDatabase - Enterprise Edition - 版本11.2.0.1 和更高版本本文档所含信息适用于所有平台 用途 本文档的目的是总结可能导致 RAC 实例崩溃的 ...

  8. encodeURI,encodeURIComponent编码

    encodeURI().encodeURIComponent().decodeURI().decodeURIComponent() URL编码 Global对象的encodeURI()和encodeU ...

  9. POJ2442:Sequence

    浅谈堆:https://www.cnblogs.com/AKMer/p/10284629.html 题目传送门:http://poj.org/problem?id=2442 我们先简化题意,假设只有两 ...

  10. BZOJ2809:[APIO2012]dispatching

    浅谈左偏树:https://www.cnblogs.com/AKMer/p/10246635.html 题目传送门:https://lydsy.com/JudgeOnline/problem.php? ...