bzoj 3545: [ONTAK2010]Peaks
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 1124 Solved: 304
[Submit][Status][Discuss]
Description
在Bytemountains有N座山峰,每座山峰有他的高度h_i。有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1。
Input
第一行三个数N,M,Q。
第二行N个数,第i个数为h_i
接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径。
接下来Q行,每行三个数v x k,表示一组询问。
Output
对于每组询问,输出一个整数表示答案。
Sample Input
1 2 3 4 5 6 7 8 9 10
1 4 4
2 5 3
9 8 2
7 8 10
7 1 4
6 7 1
6 4 8
2 1 5
10 8 10
3 4 7
3 4 6
1 5 2
1 5 6
1 5 8
8 9 2
Sample Output
1
-1
8
HINT
【数据范围】
N<=10^5, M,Q<=5*10^5,h_i,c,x<=10^9。
题解:
把M+Q个操作全部存起来,准备离线操作,添加路径的flag为1,询问的flag为0,id为i-M方便记录答案。以困难值为第一关键字,flag为第二关键字排序。这样碰到询问操作则当前的的所有连通块之间的边的困难值满足要求,记录连通块之间的信息用并查集维护一下就好了。
本题用可持久化线段树的来维护,建立N棵线段树,如果a和b之间连了一条边,则把线段树a和线段树b合并起来,由于所有线段树的形态均相同,所以只要对应的权值相加减即可。
具体看代码。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int maxn=1e5+;
inline int read(){
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
int N,M,Q,ans[*maxn];
int H[maxn],h[maxn],hash[maxn],tot;
int root[maxn],siz;
struct Tree{
int lc,rc,w;
}tr[maxn*];
inline int find(int x){
int l=,r=tot;
while(l<=r){
int mid=(l+r)>>;
if(hash[mid]<x) l=mid+;
else if(hash[mid]>x) r=mid-;
else if(hash[mid]==x) return mid;
}
return l;
} struct node{
int a,b,w;
int flag,id;
}g[maxn*];
int cmp(const node&q,const node&e){
return q.w<e.w||(q.w==e.w&&q.flag>e.flag);
} int fa[maxn];
inline int getfa(int r){
if(r!=fa[r]) fa[r]=getfa(fa[r]);
return fa[r];
} inline void insert(int &i,int l,int r,int w){
i=++siz;
tr[i].w=;
if(l==r) return ;
int mid=(l+r)>>;
if(w<=mid) insert(tr[i].lc,l,mid,w);
else insert(tr[i].rc,mid+,r,w);
}
inline int query(int i,int l,int r,int k){
if(l==r) return l;
int mid=(l+r)>>;
if(tr[tr[i].lc].w>=k)return query(tr[i].lc,l,mid,k);
else return query(tr[i].rc,mid+,r,k-tr[tr[i].lc].w);
}
inline int merge(int x,int y){
if(x==) return y;
if(y==) return x;
if(tr[x].lc==&&tr[x].rc==){
tr[x].w=tr[x].w+tr[y].w;
return x;
}
tr[x].lc=merge(tr[x].lc,tr[y].lc);
tr[x].rc=merge(tr[x].rc,tr[y].rc);
tr[x].w=tr[tr[x].lc].w+tr[tr[x].rc].w;
return x;
}
int main(){
N=read(); M=read(); Q=read();
for(int i=;i<=N;i++) H[i]=read(),h[i]=H[i];
sort(h+,h+N+);
hash[++tot]=h[];
for(int i=;i<=N;i++){//按照山的高度离散化+去重
if(h[i]!=h[i-]) hash[++tot]=h[i];
} for(int i=,a,b,w;i<=M+Q;i++){
a=read(); b=read(); w=read();
if(i<=M){
g[i].flag=;
g[i].a=a; g[i].b=b; g[i].w=w;
}
else{
g[i].id=i-M;
g[i].a=a; g[i].w=b; g[i].b=w;
}
}
sort(g+,g+M+Q+,cmp);
for(int i=;i<=N;i++) fa[i]=i;
for(int i=;i<=N;i++){
int w=find(H[i]);
insert(root[i],,tot,w);
}
for(int i=;i<=M+Q;i++){
if(g[i].flag==){//在图中加入一条边
int p=getfa(g[i].a),q=getfa(g[i].b);
if(p!=q){
fa[p]=q;
root[q]=merge(root[p],root[q]);
}
}
else{//询问
int v=getfa(g[i].a);
if(tr[root[v]].w<g[i].b) ans[g[i].id]=-;
else ans[g[i].id]=hash[query(root[v],,tot,tr[root[v]].w-g[i].b+)];
}
}
for(int i=;i<=Q;i++){
printf("%d\n",ans[i]);
}
return ;
}
bzoj 3545: [ONTAK2010]Peaks的更多相关文章
- BZOJ 3545: [ONTAK2010]Peaks( BST + 启发式合并 + 并查集 )
这道题很好想, 离线, 按询问的x排序从小到大, 然后用并查集维护连通性, 用平衡树维护连通块的山的权值, 合并就用启发式合并.时间复杂度的话, 排序是O(mlogm + qlogq), 启发式合并是 ...
- BZOJ 3545: [ONTAK2010]Peaks [Splay启发式合并]
3545: [ONTAK2010]Peaks 题意:带权图,多组询问与一个点通过边权\(\le x\)的边连通的点中点权k大值 又读错题了,输出点一直WA,问的是点权啊 本题加强版强制在线了,那这道题 ...
- ●BZOJ 3545 [ONTAK2010]Peaks(离线)
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3545 http://www.lydsy.com/JudgeOnline/problem.ph ...
- BZOJ.3545.[ONTAK2010]Peaks(线段树合并)
题目链接 \(Description\) 有n个座山,其高度为hi.有m条带权双向边连接某些山.多次询问,每次询问从v出发 只经过边权<=x的边 所能到达的山中,第K高的是多少. \(Solut ...
- bzoj 3545: [ONTAK2010]Peaks Kruskal重构树
题目: 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经 ...
- BZOJ 3545: [ONTAK2010]Peaks 启发式合并 + 离线 + Splay
Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询 ...
- BZOJ 3551: [ONTAK2010]Peaks加强版 [Kruskal重构树 dfs序 主席树]
3551: [ONTAK2010]Peaks加强版 题意:带权图,多组询问与一个点通过边权\(\le lim\)的边连通的点中点权k大值,强制在线 PoPoQQQ大爷题解传送门 说一下感受: 容易发现 ...
- BZOJ 3551/3545: [ONTAK2010]Peaks加强版 (Kruskal树+dfs序上的主席树+倍增)
Orz PoPoQQQ 学到了维护子树信息的时候用dfsdfsdfs序套主席树节省线段树空间. 学到了怎么用指针写可持久化线段树-emmm- CODE 只贴上3551加强版带强制在线的代码 #incl ...
- bzoj 3551: [ONTAK2010]Peaks加强版
Description [题目描述]同3545 Input 第一行三个数N,M,Q. 第二行N个数,第i个数为h_i 接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径. 接下来 ...
随机推荐
- NSUserDefault 保存自定义对象
由于NSUserDefaults 不支持保存自定类,保存的对象需要实现NSCoding协议,不过自定的类型就算实现了NSCoding也不可以保存,可以通过以下方法实现: //h文件 #import & ...
- 二项分布。计算binomial(100,50,0.25)将会产生的递归调用次数(算法第四版1.1.27)
算法第四版35页问题1.1.27,估计用一下代码计算binomial(100,50,0.25)将会产生的递归调用次数: public static double binomial(int n,int ...
- Big Data资料汇总
整理和翻新一下自己看过和笔记过的Big Data相关的论文和Blog Streaming & Spark In-Stream Big Data Processing Discretized S ...
- flask建立数据模型数据类型
https://blog.csdn.net/happyanger6/article/details/53947162 https://blog.csdn.net/happyanger6/article ...
- 隐藏Apache、nginx和PHP的版本号的配置方法
最近提示说有漏洞,暴露apache.nginx和php的版本号.网上搜了下,整理的方法如下: 首先说apache 在http.conf文件里添加下面两行,默认是没有的 ServerSignature ...
- px、dp、sp、mm、in、pt这些单位有什么区别?
相信每个Android新手都会遇到这个问题,希望这篇帖子能让你不再纠结. px: 即像素,1px代表屏幕上一个物理的像素点: px单位不被建议使用,因为同样100px的图片,在不同手机上显示的实际大小 ...
- python基础之小数据池、代码块、编码
一.代码块.if True: print(333) print(666) while 1: a = 1 b = 2 print(a+b) for i in '12324354': print(i) 虽 ...
- 对比python的进程和线程:多线程是假的
进程,是系统进行资源分配最小单位(拥有独立的内存单元).(python中多进程是真的) 线程,是操作系统最小的执行单位(共享内存资源),比进程还小.(python中多线程是假的,因为cpython解释 ...
- Django自定义模板函数
Django自定义模板函数 https://www.cnblogs.com/SunsetSunrise/p/7680491.html 在django中新建一个应用:listpage在listpage中 ...
- 前端 javascript 写代码方式
javascript 和python一样可以用终端写代码 写Js代码: - html文件中编写 - 临时,浏览器的终端 console