BZOJ 3545: [ONTAK2010]Peaks 启发式合并 + 离线 + Splay
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
对于每组询问,输出一个整数表示答案。
有小于等于 $x$ 这个条件十分不好办 .
考虑离线,按照 $x$ 从小到大依次加入,查询的时候直接在 $splay$ 中查询第 $k$ 大即可.
#include <cstdio>
#include <algorithm>
#include <stack>
#define N 600005
#define inf 1000000002
#define setIO(s) freopen(s".in","r",stdin) , freopen(s".out","w",stdout)
using namespace std;
int splay_cnt;
namespace IO
{
char *p1,*p2,buf[100000];
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int rd()
{
int x=0;
char c=nc();
while(c<48) c=nc();
while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc();
return x;
}
};
struct Edge
{
int u , v , c ;
}ed[N];
bool cmp(Edge a, Edge b)
{
return a.c < b.c;
}
struct Ask
{
int u , x , k , id ;
}as[N];
bool cmp2(Ask a, Ask b)
{
return a.x < b.x;
}
#define lson ch[x][0]
#define rson ch[x][1]
stack <int> S;
int answer[N], h[N], size[N], f[N], ch[N][2], siz[N], val[N], rt[N], p[N], mk = 0;
inline void init(int sz)
{
for(int i = 1; i <= sz ; ++i) S.push(i);
for(int i = 1; i <= sz ; ++i) p[i] = i, size[i] = 1;
}
int find(int x)
{
return p[x] == x ? x : p[x] = find(p[x]);
}
inline int newnode()
{
int u = S.top(); S.pop();
return u;
}
inline int get(int x)
{
return ch[f[x]][1] == x;
}
inline void pushup(int x)
{
siz[x] = siz[lson] + siz[rson] + 1;
}
inline void rotate(int x)
{
int old = f[x], fold = f[old], which = get(x);
ch[old][which] = ch[x][which ^ 1], f[ch[old][which]] = old;
ch[x][which ^ 1] = old, f[old] = x, f[x] = fold;
if(fold) ch[fold][ch[fold][1] == old] = x;
pushup(old), pushup(x);
}
inline void splay(int x, int &tar)
{
int u = f[tar];
for(int fa; (fa = f[x]) ^ u; rotate(x))
if(f[fa] ^ u)
rotate(get(fa) == get(x) ? fa : x);
tar = x;
}
inline int kth(int x, int k)
{
if(siz[x] < k) return inf;
while(1)
{
if(k > siz[rson])
{
k -= (siz[rson] + 1);
if(!k) return x;
else x = lson;
}
else x = rson;
}
}
inline void insert(int &x, int ff, int v)
{
if(!x)
{
mk = x = newnode();
f[x] = ff, val[x] = v, pushup(x);
return;
}
insert(ch[x][v > val[x]], x, v), pushup(x);
}
inline void DFS(int y, int x)
{
if(lson) DFS(y, lson);
if(rson) DFS(y, rson);
int v = val[x];
S.push(x), val[x] = siz[x] = lson = rson = f[x] = 0, insert(rt[y], 0, v), ++splay_cnt;
if(splay_cnt % 6 == 0) splay(mk, rt[y]);
}
inline void connect(int o)
{
int u = ed[o].u, v = ed[o].v;
int x = find(u), y = find(v);
if(x ^ y)
{
if(size[y] < size[x]) swap(x, y);
p[x] = y, size[y] += size[x], DFS(y, rt[x]);
}
}
int main()
{
using namespace IO;
// setIO("input");
int n, m, q, i, j;
n = rd(), m = rd(), q = rd(), init(n);
for(i = 1; i <= n ; ++i) h[i] = rd(), insert(rt[i], 0, h[i]);
for(i = 1; i <= m ; ++i) ed[i].u = rd(), ed[i].v = rd(), ed[i].c = rd();
sort(ed + 1, ed + 1 + m, cmp);
for(i = 1; i <= q ; ++i)
{
as[i].u = rd(), as[i].x = rd(), as[i].k = rd(), as[i].id = i;
}
sort(as + 1, as + 1 + q, cmp2);
for(i = j = 1; i <= q; ++i)
{
while(ed[j].c <= as[i].x && j <= m) connect(j), ++j;
int l = kth(rt[find(as[i].u)], as[i].k);
answer[as[i].id] = (l == inf ? inf : val[l]);
if(l ^ inf)
{
++splay_cnt;
if(splay_cnt % 6 == 0) splay(l, rt[find(as[i].u)]);
}
}
for(i = 1; i <= q; ++i) printf("%d\n",answer[i] == inf ? -1 : answer[i]);
return 0;
}
BZOJ 3545: [ONTAK2010]Peaks 启发式合并 + 离线 + Splay的更多相关文章
- BZOJ 3545: [ONTAK2010]Peaks [Splay启发式合并]
3545: [ONTAK2010]Peaks 题意:带权图,多组询问与一个点通过边权\(\le x\)的边连通的点中点权k大值 又读错题了,输出点一直WA,问的是点权啊 本题加强版强制在线了,那这道题 ...
- BZOJ 3545: [ONTAK2010]Peaks( BST + 启发式合并 + 并查集 )
这道题很好想, 离线, 按询问的x排序从小到大, 然后用并查集维护连通性, 用平衡树维护连通块的山的权值, 合并就用启发式合并.时间复杂度的话, 排序是O(mlogm + qlogq), 启发式合并是 ...
- ●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
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1124 Solved: 304[Submit][Status][Discuss] Descripti ...
- bzoj 3545: [ONTAK2010]Peaks Kruskal重构树
题目: 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经 ...
- 【loj6041】「雅礼集训 2017 Day7」事情的相似度 后缀自动机+STL-set+启发式合并+离线+扫描线+树状数组
题目描述 给你一个长度为 $n$ 的01串,$m$ 次询问,每次询问给出 $l$ .$r$ ,求从 $[l,r]$ 中选出两个不同的前缀的最长公共后缀长度的最大值. $n,m\le 10^5$ 题解 ...
- BZOJ.3510.首都(LCT 启发式合并 树的重心)
题目链接 BZOJ 洛谷 详见这. 求所有点到某个点距离和最短,即求树的重心.考虑如何动态维护. 两棵子树合并后的重心一定在两棵树的重心之间那条链上,所以在合并的时候用启发式合并,每合并一个点检查sz ...
- BZOJ 3551: [ONTAK2010]Peaks加强版 [Kruskal重构树 dfs序 主席树]
3551: [ONTAK2010]Peaks加强版 题意:带权图,多组询问与一个点通过边权\(\le lim\)的边连通的点中点权k大值,强制在线 PoPoQQQ大爷题解传送门 说一下感受: 容易发现 ...
随机推荐
- C++ 优先队列 priority_queue
平时定义的时候,直接上就完事了: priority_queue<int>Q; 默认大根堆. 之前很菜的时候不知道小根堆怎么写,还在考场上干过加个负号甩到大根堆里面去的蠢事. 它的完整形式呢 ...
- Keytool生成证书
一.生成证书keytool -genkey -alias 别名 -keyalg RSA -keysize 1024(密钥位数) -keypass 密码 -validity 365(默认90天) -ke ...
- scrapy 启动
虚拟环境安装好了之后,scrapy 框架安装好了以后: workon article_spider (项目名称) scrapy startproject Article Spider 工程目录 ...
- ll按时间排序和查看目录下文件数
查询文件并以降序排列:ll -t 查询文件并以升序排列:ll -t | tac 查询目录下文件数:ll|wc -l
- C语言博客作业05
这个作业属于哪个课程 C语言程序设计II 这个作业要求在那里 https://edu.cnblogs.com/campus/zswxy/CST2019-3/homework/9827 我在这个课程的目 ...
- jquery validate 自定义校验方法
1.引入JS jquery.min.js jquery.validate.min.js messages_zh.min.js 2.添加验证方法,第一个参数为验证方法的名称,第二个参数为验证方法. $. ...
- 微软宣布加入 OpenJDK,打不过就改变 Java 未来!
近日,微软的 Bruno Borges 在 OpenJDK 邮件列表中发布了一条消息,内容包含接下来发生的事情以及微软如何开始将其团队整合到 OpenJDK 社区. 在邮件中,Bruno Borges ...
- python中判断字典中是否存在某个键
python3 中采用 in 方法 #判断字典中某个键是否存在 arr = {"int":"整数","float":"浮点&quo ...
- 从入门到自闭之Python 基础习题训练
""" name = input(">>>")通过代码来验证name变量是什么数据类型? """ na ...
- 修改文件夹的所有者为www
切换到root用户:su - root 修改文件所属用户和用户组:chown 用户:用户组 文件名如果用户和用户组是www,那么需要执行命令如下:chown www:www filename -R ( ...