题目:

在Bytemountains有N座山峰,每座山峰有他的高度h_i。有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1。

题解:

这道题貌似是Kruskal重构树的板子题.

很长时间以前做了加强版,现在才发现还有未加强版.

赶紧把代码粘了过来水了过去.

(还记得写这份代码的时候被卡内存,用了po姐的主席树模板才过去的)

#include <cstdio>
#include <cstring>
#include <cassert>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
x=0;char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
inline int cat_max(const int &a,const int &b){return a>b ? a:b;}
inline int cat_min(const int &a,const int &b){return a<b ? a:b;}
const int maxn = 200200;
const int inf = 0x3f3f3f3f;
struct Edge{
int to,next;
}G[maxn];
int head[maxn],cnt;
void add(int u,int v){
G[++cnt].to = v;
G[cnt].next = head[u];
head[u] = cnt;
}
struct edge{
int u,v,d;
bool friend operator < (const edge &a,const edge &b){
return a.d < b.d;
}
}zs[500500];
int n,w[maxn],ufa[maxn],m,q;
int fa[maxn][20],dis[maxn][20];
int find(int u){
return ufa[u] == u ? u : ufa[u] = find(ufa[u]);
}
void Kruskal(){
sort(zs+1,zs+m+1);
int nc = 0;
for(int i=1;i<=m;++i){
int x = find(zs[i].u);
int y = find(zs[i].v);
if(x != y){
ufa[x] = ufa[y] = ++n;
ufa[n] = n;
fa[x][0] = n;fa[y][0] = n;
dis[x][0] = dis[y][0] = zs[i].d;
add(n,x);add(n,y);
if(++nc == n-1) break;
}
}
}
int dfn[maxn],ind[maxn],oud[maxn];
int dfs_clock;
#define v G[i].to
void dfs(int u){
ind[u] = ++dfs_clock;
dfn[ind[u]] = w[u];
for(int i = head[u];i;i=G[i].next){
dfs(v);
}
oud[u] = dfs_clock;
}
#undef v
struct Node{
Node *ls,*rs;
int num;
void* operator new (size_t size,Node *_,Node *__,int ___);
}*tree[maxn],*mempool,*C,*null;
void* Node :: operator new (size_t size,Node *_,Node *__,int ___){
if(C==mempool){
C=new Node[1<<15];
mempool=C+(1<<15);
}
C->ls=_;
C->rs=__;
C->num=___;
return C++;
}
Node* build(Node *p,int x,int y,int val){
int mid=x+y>>1;
if(x==y) return new (null,null,p->num+1) Node;
if(val<=mid) return new (build(p->ls,x,mid,val),p->rs,p->num+1) Node;
else return new (p->ls,build(p->rs,mid+1,y,val),p->num+1) Node;
}
int Kth(Node *p1,Node *p2,int x,int y,int k){
int l = x,r = y;
while(l != r){
int x = p2->rs->num-p1->rs->num;
int mid = l+r >> 1;
if(k <= x){
p1 = p1->rs;p2 = p2->rs;
l = mid+1;
}else{
p1 = p1->ls;p2 = p2->ls;
r = mid;k -= x;
}
}return l;
}
int get_rt(int x,int y){
for(int j=19;~j;--j){
if(fa[x][j] && dis[x][j] <= y){
x = fa[x][j];
}
}
return x;
}
int main(){
read(n);read(m);read(q);
for(int i=1;i<=n;++i){
read(w[i]);ufa[i] = i;
}
for(int i=1;i<=m;++i){
read(zs[i].u);read(zs[i].v);
read(zs[i].d);
}
Kruskal();
for(int j = 1;j<= 19;++j){
for(int i=1;i<=n;++i){
fa[i][j] = fa[fa[i][j-1]][j-1];
dis[i][j] = cat_max(dis[i][j-1],dis[fa[i][j-1]][j-1]);
}
}
dfs(n);
null=new (0x0,0x0,0) Node;
null->ls=null->rs=null;
tree[0] = null;
for(int i=1;i<=n;++i){
tree[i] = build(tree[i-1],0,1000000000,dfn[i]);
}
int u,v,k,ans = 0;
while(q--){
read(u);read(v);read(k); int x = get_rt(u,v);
if(oud[x] - ind[x] + 1 < k){
puts("-1");
ans = 0;
continue;
}
ans = Kth(tree[ind[x]-1],tree[oud[x]],0,1000000000,k);
if(ans == 0){
puts("-1");
continue;
}
printf("%d\n",ans);
}
getchar();getchar();
return 0;
}

bzoj 3545: [ONTAK2010]Peaks Kruskal重构树的更多相关文章

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

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

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

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

  3. 【BZOJ 3732】 Network Kruskal重构树+倍增LCA

    Kruskal重构树裸题, Sunshine互测的A题就是Kruskal重构树,我通过互测了解到了这个神奇的东西... 理解起来应该没什么难度吧,但是我的Peaks连WA,,, 省选估计要滚粗了TwT ...

  4. BZOJ 3545: [ONTAK2010]Peaks( BST + 启发式合并 + 并查集 )

    这道题很好想, 离线, 按询问的x排序从小到大, 然后用并查集维护连通性, 用平衡树维护连通块的山的权值, 合并就用启发式合并.时间复杂度的话, 排序是O(mlogm + qlogq), 启发式合并是 ...

  5. BZOJ 3545: [ONTAK2010]Peaks [Splay启发式合并]

    3545: [ONTAK2010]Peaks 题意:带权图,多组询问与一个点通过边权\(\le x\)的边连通的点中点权k大值 又读错题了,输出点一直WA,问的是点权啊 本题加强版强制在线了,那这道题 ...

  6. BZOJ 4242: 水壶(Kruskal重构树 + Bfs)

    题意 一块 \(h ∗ w\) 的区域,存在障碍.空地.\(n\) 个建筑,从一个建筑到另一个建筑的花费为:路径上最长的连续空地的长度. \(q\) 次询问:从建筑 \(s_i\) 到 \(t_i\) ...

  7. luogu4197 Peaks (kruskal重构树+主席树)

    按照边权排序建出kruskal重构树,每次就变成了先找一个权值<=x的最远的祖先,然后看这个子树的第k小.离散化一下,在dfs序上做主席树即可 而且只需要建叶节点的主席树 注意输出的是第k小点的 ...

  8. 洛谷P4197 Peaks(Kruskal重构树 主席树)

    题意 题目链接 往后中文题就不翻译了qwq Sol 又是码农题..出题人这是强行把Kruskal重构树和主席树拼一块了啊.. 首先由于给出的限制条件是<=x,因此我们在最小生成树上走一定是最优的 ...

  9. BZOJ 5415: [Noi2018]归程(kruskal重构树)

    解题思路 \(NOI2018\)的\(Day1\) \(T1\),当时打网络赛的时候不会做.学了一下\(kruskal\)重构树后发现问题迎刃而解了.根据\(kruskal\)的性质,如果要找从\(u ...

随机推荐

  1. poj1845(二分快速求等比数列模M和)

    Sumdiv Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 17039   Accepted: 4280 Descripti ...

  2. spring mvc注解和spring boot注解

    1 spring mvc和spring boot之间的关系 spring boot包含spring mvc.所以,spring mvc的注解在spring boot总都是可以用的吗? spring b ...

  3. 关于logback

    1 logback是一个日志框架 2 logback的构成 LogBack被分为3个组件,logback-core, logback-classic 和 logback-access. 其中logba ...

  4. 【python】-- 协程介绍及基本示例、协程遇到IO操作自动切换、协程(gevent)并发爬网页

    协程介绍及基本示例 协程,又称微线程,纤程.英文名Coroutine.一句话说明什么是协程:协程是一种用户态的轻量级线程. 协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和栈保存到其他 ...

  5. ASP获取上月本月下月的第一天和最后一天

    上月第一天:<%=dateadd("m",-1,year(date)&"-"&month(date)&"-1" ...

  6. You can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode.

    [root@localhost dreamstart]# composer installLoading composer repositories with package informationI ...

  7. IOS - 执行时 (多态)

    一 多态概述          多态指同一操作作用于不同的对象.能够有不同的解释.产生不同的执行结果.它是面向对象程序设计(OOP)的一个重要特征,动态类型能使程序直到执行时才确定对象的所属类.其详细 ...

  8. Broadcast Intent & Broadcast Receiver

    当Android系统发生某种状况,必须通知所有程序进行处理时,例如电量不足等,可利用Broadcast Intent对象的功能来进行信息广播. 运行机制包括两部:送出Intent对象的程序:监听广播信 ...

  9. ppm图像相关

    PPM图像格式介绍 直接拿具体的数据来说明是最直接的,使用ue打开ppm文件,采用的都是十六进制asc码表示的,这里要注意地址00000000h中的最后一个字母是始终不变的,这原来没注意晕了我好久,第 ...

  10. 磁盘分区对齐详解与配置 – Linux篇

    在之前一篇<磁盘分区对齐详解与配置 – Windows篇>中,我介绍了磁盘分区对齐的作用和适用于MBR和GPT的两种磁盘类型的配置,以及Windows平台设置磁盘分区对齐的方法. 本文作为 ...