欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


题目传送门 - BZOJ3545


题意概括

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

对于每组询问,输出一个整数表示答案。


题解

这题卡常,要读入优化。

代码

#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=100005,M=500005,S=N*2,Inf=1e9+5;
bool isd(char ch){
return '0'<=ch&&ch<='9';
}
void read(int &x){
x=0;
char ch=getchar();
while (!isd(ch))
ch=getchar();
while (isd(ch))
x=(x<<1)+(x<<3)+ch-48,ch=getchar();
}
struct Edge{
int x,y,z;
void Read(){
read(x),read(y),read(z);
}
}e[M];
bool cmpz(Edge a,Edge b){
return a.z<b.z;
}
struct MQset{//并查集
int cnt,fa[N*2];
void clear(){cnt=0;}
int getf(int k){return fa[k]==k?k:fa[k]=getf(fa[k]);}
void push(int x){fa[x]=x;}
void merge(int x,int y){fa[getf(x)]=getf(y);}
}s;
int n,m,q,h[N];
int fa[S],lc[S],rc[S],val[S],cnt;
int anst[S][20],time,in[S],out[S],dfn[S];
void dfs(int rt){
anst[rt][0]=fa[rt];
for (int i=1;i<20;i++)
anst[rt][i]=anst[anst[rt][i-1]][i-1];
in[rt]=time;
if (!lc[rt])
dfn[++time]=rt;
else
dfs(lc[rt]),dfs(rc[rt]);
out[rt]=time;
}
const int SIZE=N*2*20*2;
int Ha[N],hs;
int ls[SIZE],rs[SIZE],sum[SIZE],total,root[N];
void LSH(){
int hs_=1;
sort(Ha+1,Ha+hs+1);
for (int i=2;i<=hs;i++)
if (Ha[i]!=Ha[i-1])
Ha[++hs_]=Ha[i];
hs=hs_;
}
int find(int x){
return lower_bound(Ha+1,Ha+hs+1,x)-Ha;
}
void build(int &rt,int L,int R){
rt=++total;
sum[rt]=0;
if (L==R)
return;
int mid=(L+R)>>1;
build(ls[rt],L,mid);
build(rs[rt],mid+1,R);
}
void add(int prt,int &rt,int L,int R,int pos){
rt=++total;
if (L==R){
sum[rt]=sum[prt]+1;
return;
}
int mid=(L+R)>>1;
if (pos<=mid)
add(ls[prt],ls[rt],L,mid,pos),rs[rt]=rs[prt];
else
add(rs[prt],rs[rt],mid+1,R,pos),ls[rt]=ls[prt];
sum[rt]=sum[ls[rt]]+sum[rs[rt]];
}
int query(int prt,int rt,int L,int R,int k){
if (L==R)
return Ha[L];
int Rz=sum[rs[rt]]-sum[rs[prt]];
int mid=(L+R)>>1;
if (Rz>=k)
return query(rs[prt],rs[rt],mid+1,R,k);
else
return query(ls[prt],ls[rt],L,mid,k-Rz);
}
int find(int x,int v){
for (int i=19;i>=0;i--)
if (val[anst[x][i]]<=v)
x=anst[x][i];
return x;
}
int main(){
read(n),read(m),read(q);
for (int i=1;i<=n;i++)
read(h[i]),Ha[i]=h[i];
hs=n;
LSH();
for (int i=1;i<=n;i++)
h[i]=find(h[i]);
for (int i=1;i<=m;i++)
e[i].Read();
sort(e+1,e+m+1,cmpz);
s.clear();
for (int i=1;i<=n;i++){
s.push(i);
fa[i]=lc[i]=rc[i]=val[i]=0;
}
cnt=n;
for (int i=1;i<=m;i++){
int x=e[i].x,y=e[i].y,z=e[i].z;
x=s.getf(x),y=s.getf(y);
if (x==y)
continue;
s.push(++cnt);
fa[x]=fa[y]=cnt;
fa[cnt]=0,lc[cnt]=x,rc[cnt]=y,val[cnt]=z;
s.fa[x]=s.fa[y]=cnt;
}
val[0]=Inf;
time=0;
dfs(cnt);
build(root[0],1,n);
for (int i=1;i<=n;i++)
add(root[i-1],root[i],1,n,h[dfn[i]]);
for (int i=1;i<=q;i++){
int v,x,k,y;
read(v),read(x),read(k);
y=find(v,x);
if (out[y]-in[y]<k)
puts("-1");
else
printf("%d\n",query(root[in[y]],root[out[y]],1,n,k));
}
return 0;
}

  

BZOJ3545 [ONTAK2010]Peaks kruskal 并查集 主席树 dfs序的更多相关文章

  1. BZOJ3551 [ONTAK2010]Peaks加强版 kruskal 并查集 主席树 dfs序

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3551 题意概括 Description 在Bytemountains有N座山峰,每座山峰有他的高度 ...

  2. [ONTAK2010]Peaks kruskal重构树,主席树

    [ONTAK2010]Peaks kruskal重构树练手题. LG传送门竟然不强制在线?看到离线水过很不爽:B站强制在线版传送门 看到"询问从点\(v\)开始只经过困难值小于等于\(x\) ...

  3. Codeforces 571D - Campus(并查集+线段树+DFS 序,hot tea)

    Codeforces 题目传送门 & 洛谷题目传送门 看到集合的合并,可以本能地想到并查集. 不过这题的操作与传统意义上的并查集不太一样,传统意义上的并查集一般是用来判断连通性的,而此题还需支 ...

  4. 51 nod 1681 公共祖先 (主席树+dfs序)

    1681 公共祖先 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题   有一个庞大的家族,共n人.已知这n个人的祖辈关系正好形成树形结构(即父亲向儿子连边). 在另 ...

  5. 【BZOJ1803】Spoj1487 Query on a tree III 主席树+DFS序

    [BZOJ1803]Spoj1487 Query on a tree III Description You are given a node-labeled rooted tree with n n ...

  6. BZOJ3545&3551[ONTAK2010]Peaks——kruskal重构树+主席树+dfs序+树上倍增

    题目描述 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只 ...

  7. 【BZOJ-3545&3551】Peaks&加强版 Kruskal重构树 + 主席树 + DFS序 + 倍增

    3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1202  Solved: 321[Submit][Sta ...

  8. 洛谷P3402 【模板】可持久化并查集 [主席树,并查集]

    题目传送门 可持久化并查集 n个集合 m个操作 操作: 1 a b 合并a,b所在集合 2 k 回到第k次操作之后的状态(查询算作操作) 3 a b 询问a,b是否属于同一集合,是则输出1否则输出0 ...

  9. bzoj2733 离线+并查集+主席树

    https://www.lydsy.com/JudgeOnline/problem.php?id=2733 网上清一色的合并线段树题解,我又不会,只能自己胡来,没想到Rush过去了 永无乡包含 n 座 ...

随机推荐

  1. WF控制台工作流(1)

    简单使用WF工作流示例: using System; using System.Linq; using System.Activities; using System.Activities.State ...

  2. Postfix 邮件服务 - dovecot 服务

    dovecot 是一个开源的IMAP和POP3邮件服务器 收件协议 (SMTP 传输发件)POP/IMAP 是MUA从邮件服务器中读取邮件时使用的协议.其中,与POP3是从邮件服务器中下载邮件存起来, ...

  3. [C++]指针和指向数组的指针[一维数组与指针]

     1.一维数组与指针      形如:int型 数组 a[10]                1)&a[0]  地址常量;地址类型:int *型   ; 存储数组a的首地址          ...

  4. [C++]栈区(栈)与堆区(类链表)[转/摘]

     一.预备知识—程序的内存分配   一个由C/C++编译的程序占用的内存分为以下几个部分    1.栈区(stack)—   由编译器自动分配释放   ,存放函数的参数值,局部变量的值等.其    操 ...

  5. NFS配置不当导致的那些事儿

    NFS(Network File System):是FreeBSD支持的文件系统中的一种,它允许网络中的计算机之间通过TCP/IP网络共享资源: NFS配置:(声明:以下NFS实验是在RedHat7上 ...

  6. Mask RCNN 简单使用

    涉及到的知识点补充: FasterRCNN:https://www.cnblogs.com/wangyong/p/8513563.html RoIPooling.RoIAlign:https://ww ...

  7. linux笔记_day03

    1.命令行展开{} mkdir -p a/b/{c,d/e} 2.-v verbose 详细的 3.touch touch - change file timestamps 4.stat 文件  显示 ...

  8. SpringMVC集成MongoDb

    (1)pom添加相关依赖 <dependency> <groupId>org.springframework.data</groupId> <artifact ...

  9. How to Repair GRUB2 When Ubuntu Won’t Boot

    Ubuntu and many other Linux distributions use the GRUB2 boot loader. If GRUB2 breaks—for example, if ...

  10. Android APP—— 开发入门教程

    一.SDK下载 下载:adt-bundle-windows-x86_64-20140702.zip(20140702 已经是最后版本了) 解压出来如下: 点击Eclipse安装 创建一个新的工作空间安 ...