[BZOJ4009][HNOI2015]接水果(整体二分)
[HNOI2015]接水果
时间限制:60s 空间限制:512MB
题目描述
风见幽香非常喜欢玩一个叫做 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≤c≤10^9,a不等于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<=40000。
题目来源
没有写明来源
类似HNOI2017的影魔,思想是把对象映射到平面上。
代码用时:1.5h。非常裸,整体二分加扫描线,树状数组代替线段树既省时有省力。
#include<cstdio>
#include<algorithm>
#define rep(i,l,r) for (int i=l; i<=r; i++)
#define For(i,x) for (int i=h[x],k; i; i=nxt[i])
using namespace std; const int N=;
int n,m,q,a,b,c,k,u,cnt,fa[N][],dfn[N],tim,lst[N],v[N],dep[N],ans[N],sum[N],nxt[N],h[N],to[N],tot;
struct P{ int x1,x2,y1,y2,v; }p[N];
struct D{ int x,y1,y2,v,id; }d[N];
struct Q{int x,y,k,id; }pnt[N],t1[N],t2[N];
bool operator <(P a,P b){ return a.v<b.v; }
bool operator <(D a,D b){ return a.x==b.x ? a.id<b.id : a.x<b.x; }
void add(int u,int v){ nxt[++tot]=h[u]; h[u]=tot; to[tot]=v; }
int que(int x){ int res=; for (; x; x-=(x&(-x))) res+=v[x]; return res; } void mdf(int l,int r,int k){
for (int i=l; i<=n; i+=(i&(-i))) v[i]+=k;
for (int i=r+; i<=n; i+=(i&(-i))) v[i]-=k;
} void dfs(int x){
dfn[x]=++tim;
rep(i,,) fa[x][i]=fa[fa[x][i-]][i-];
For(i,x) if ((k=to[i])!=fa[x][]) fa[k][]=x,dep[k]=dep[x]+,dfs(k);
lst[x]=tim;
} int go(int a,int h){ for (int i=; ~i; i--) if (h&(<<i)) a=fa[a][i]; return a; } int lca(int a,int b){
if (dep[a]<dep[b]) swap(a,b);
a=go(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){ rep(i,st,ed) ans[pnt[i].id]=p[l].v; return; }
int mid=(l+r)>>,sz=;
rep(i,l,mid){
d[++sz]=(D){p[i].x1,p[i].y1,p[i].y2,,};
d[++sz]=(D){p[i].x2,p[i].y1,p[i].y2,-,n+};
}
rep(i,st,ed) d[++sz]=(D){pnt[i].x,pnt[i].y,,,i};
sort(d+,d+sz+);
rep(i,,sz)
if (st<=d[i].id && d[i].id<=ed) sum[d[i].id]=que(d[i].y1);
else mdf(d[i].y1,d[i].y2,d[i].v);
int a=,b=;
rep(i,st,ed)
if (sum[i]>=pnt[i].k) t1[++a]=pnt[i];
else t2[++b]=(Q){pnt[i].x,pnt[i].y,pnt[i].k-sum[i],pnt[i].id};
rep(i,st,st+a-) pnt[i]=t1[i-st+];
rep(i,st+a,ed) pnt[i]=t2[i-st-a+];
solve(l,mid,st,st+a-); solve(mid+,r,st+a,ed);
} int main(){
freopen("bzoj4009.in","r",stdin);
freopen("bzoj4009.out","w",stdout);
scanf("%d%d%d",&n,&m,&q);
rep(i,,n-) scanf("%d%d",&a,&b),add(a,b),add(b,a);
dfs();
rep(i,,m){
scanf("%d%d%d",&a,&b,&c); u=lca(a,b);
if (dfn[a]>dfn[b]) swap(a,b);
if (u!=a) p[++cnt]=(P){dfn[a],lst[a],dfn[b],lst[b],c};
else{
int w=go(b,dep[b]-dep[a]-);
p[++cnt]=(P){,dfn[w]-,dfn[b],lst[b],c};
if (lst[w]<n) p[++cnt]=(P){dfn[b],lst[b],lst[w]+,n,c};
}
}
sort(p+,p+cnt+);
rep(i,,q){
scanf("%d%d%d",&a,&b,&k);
if (dfn[a]>dfn[b]) swap(a,b);
pnt[i]=(Q){dfn[a],dfn[b],k,i};
}
solve(,cnt,,q);
rep(i,,q) printf("%d\n",ans[i]);
return ;
}
[BZOJ4009][HNOI2015]接水果(整体二分)的更多相关文章
- [bzoj4009] [HNOI2015]接水果 整体二分+扫描线+dfs序+树状数组
Description 风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果. 由于她已经DT FC 了The big black, 她觉得这个游戏太简单了,于是发明了一个更 加 ...
- bzoj4009 [HNOI2015]接水果 整体二分+扫描线+树状数组+dfs序
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4009 题解 考虑怎样的情况就会有一个链覆盖另一个链. 设被覆盖的链为 \(a - b\),覆盖 ...
- BZOJ4009:[HNOI2015]接水果(整体二分版)
浅谈离线分治算法:https://www.cnblogs.com/AKMer/p/10415556.html 题目传送门:https://lydsy.com/JudgeOnline/problem.p ...
- BZOJ.4009.[HNOI2015]接水果(整体二分 扫描线)
LOJ BZOJ 洛谷 又是一个三OJ rank1!=w= \(Description\) (还是感觉,为啥非要出那种题目背景啊=-=直接说不好么) 给定一棵树和一个路径集合(每条路径有一个权值).\ ...
- BZOJ 4009: [HNOI2015]接水果 (整体二分+扫描线 树状数组)
整体二分+扫描线 树状数组 具体做法看这里a CODE #include <cctype> #include <cstdio> #include <cstring> ...
- [HNOI2015]接水果[整体二分]
[HNOI2015]接水果 给出一个树上路径集合\(S\) 多次询问\(x,y\)中的\(k\)小值 如果你问我数列上那么我会 树上的话 树上差分了吧直接?- 令 \(st_x<st_y\) 1 ...
- 2018.10.02 bzoj4009: [HNOI2015]接水果(整体二分)
传送门 整体二分好题. 考虑水果被盘子接住的条件. 不妨设水果表示的路径为(x1,y1)(x_1,y_1)(x1,y1),盘子表示的为(x2,y2)(x_2,y_2)(x2,y2) 不妨设df ...
- [HNOI2015][bzoj4009] 接水果 [整体二分+扫描线]
题面 传送门 思路 本题其实有在线做法......但是太难写了,退而求其次写了离线 基本思路就是,考虑一个盘子以及它能接到的所有水果 可以发现,这个水果的端点一定在这个盘子两端的"子树&qu ...
- bzoj4009: [HNOI2015]接水果(整体二分)
题目描述 风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果.由于她已经DT FC 了The big black, 她觉得这个游戏太简单了,于是发明了一个更加难的版本. 首先有 ...
随机推荐
- 微信小程序开发(二)创建小程序
安装完“微信Web开发者工具”后,手机扫描二维码进入页面. 点击“添加项目”,填入之前获得的AppID(无AppID可忽略),输入项目名称“Hello WXapplet”,选定本地文件夹作为项目目录. ...
- easyUI导出数据
easyUI导出数据模式 后台: //导出数据 public function index_doExport() { $search['diqu']=$_POST['diqu']; $search[' ...
- Spring Boot中使用Spring-data-jpa让数据访问更简单、更优雅
在上一篇Spring中使用JdbcTemplate访问数据库中介绍了一种基本的数据访问方式,结合构建RESTful API和使用Thymeleaf模板引擎渲染Web视图的内容就已经可以完成App服务端 ...
- VC拷贝字符串到剪切板
] ="中华人民共和国"; DWORD dwLength = ; // 要复制的字串长度 HANDLE hGlobalMemory = GlobalAlloc(GHND, dwLe ...
- python3爬虫.4.下载煎蛋网妹子图
开始我学习爬虫的目标 ----> 煎蛋网 通过设置User-Agent获取网页,发现本该是图片链接的地方被一个js函数代替了 于是全局搜索到该函数 function jandan_load_im ...
- Masquerade strikes back Gym - 101911D(补题) 数学
https://vjudge.net/problem/Gym-101911D 具体思路: 对于每一个数,假设当前的数是10 分解 4次,首先 1 10 这是一对,然后下一次就记录 10 1,这样的话直 ...
- ubuntu永久修改主机名
1.查看主机名 在Ubuntu系统中,快速查看主机名有多种方法:其一,打开一个GNOME终端窗口,在命令提示符中可以看到主机名,主机名通常位于“@”符号后:其二,在终端窗口中输入命令:hostname ...
- 1-编程基础及Python环境部署
目录 1 编程基础 1.1 基本概念 1.2 语言分类 1.3 高级语言的发展 2 程序 3 python的语言介绍 4 Python的解释器 5 Python版本区别 6 Python安装 6.1 ...
- 摘: 给Shapre命名
有两种解决方式: 在 VBA 中将slide中的Shape命名,改变shape.name即可. 另外一种方式就是有点投机取巧:你可以点击shap,右键选择web/alternativetext做些标记 ...
- centos如何设置定时任务
1.crontab -e 打开任务列表,输入i开始编写面之后按esc退出编写默写,:wq保存退出即可. 2.关于时间格式的定义,,请使用下面的网站 https://crontab.guru/#00_0 ...
