[ONTAK2010]Peaks
题目大意:
一个图上有$n(n\leq100000)$个带权点,$m(m\leq500000)$条带权边。有$q(q\leq500000)$组询问,每次询问从点$v$出发,只经过权值小于等于$x$的边能到达的点中,权值第$k$大的点权。
思路:
离线处理每个询问。将询问和边分别按权值排序,处理到当前询问时,将权值小于等于$x$的边加入到图中。用权值线段树维护每个连通块的权值。点的联通情况用并查集维护(相当于Kruskal),权值线段树直接合并。时间复杂度$O(n\log n+m\log m+q\log q+q\log n)$。
#include<cstdio>
#include<cctype>
#include<algorithm>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'';
while(isdigit(ch=getchar())) x=(((x<<)+x)<<)+(ch^'');
return x;
}
const int N=,M=,Q=;
int h[N],tmp[N],ans[Q];
struct Edge {
int u,v,w;
bool operator < (const Edge &another) const {
return w<another.w;
}
};
Edge e[M];
struct Query {
int v,x,k,id;
bool operator < (const Query &another) const {
return x<another.x;
}
};
Query q[Q];
struct DisjointSet {
int anc[N];
int find(const int &x) {
return x==anc[x]?x:anc[x]=find(anc[x]);
}
void reset(const int &n) {
for(register int i=;i<=n;i++) anc[i]=i;
}
void merge(const int &x,const int &y) {
anc[find(y)]=find(x);
}
bool same(const int &x,const int &y) {
return find(x)==find(y);
}
};
DisjointSet s;
class SegmentTree {
private:
struct Node {
int val;
Node *left,*right;
Node(const int &v):val(v),left(NULL),right(NULL) {}
};
void modify(Node *&p,const int &b,const int &e,const int &x) {
p=new Node();
if(b==e) return;
const int mid=(b+e)>>;
if(x<=mid) modify(p->left,b,mid,x);
if(x>mid) modify(p->right,mid+,e,x);
}
public:
Node *root[N];
void reset(const int &n) {
for(register int i=;i<=n;i++) {
modify(root[i],,tmp[],h[i]);
}
}
void merge(Node *&p1,Node *const &p2) {
if(!p1) {
p1=p2;
return;
}
if(!p2) return;
p1->val+=p2->val;
merge(p1->left,p2->left);
merge(p1->right,p2->right);
delete p2;
}
int query(const Node *const &p,const int &b,const int &e,const int &k) const {
if(p->val<k) return -;
if(b==e) return b;
const int mid=(b+e)>>;
if(!p->right) return query(p->left,b,mid,k);
if(k<=p->right->val) return query(p->right,mid+,e,k);
return query(p->left,b,mid,k-p->right->val);
}
};
SegmentTree t;
inline void add_edge(const Edge &e) {
if(s.same(e.u,e.v)) return;
t.merge(t.root[s.find(e.u)],t.root[s.find(e.v)]);
s.merge(e.u,e.v);
}
int main() {
const int n=getint(),m=getint(),cnt_q=getint();
for(register int i=;i<=n;i++) {
tmp[i]=h[i]=getint();
}
std::sort(&tmp[],&tmp[n]+);
tmp[]=std::unique(&tmp[],&tmp[n]+)-&tmp[];
for(register int i=;i<=n;i++) {
h[i]=std::lower_bound(&tmp[],&tmp[tmp[]]+,h[i])-&tmp[];
}
for(register int i=;i<m;i++) {
const int u=getint(),v=getint(),w=getint();
e[i]=(Edge){u,v,w};
}
std::sort(&e[],&e[m]);
for(register int i=;i<cnt_q;i++) {
const int v=getint(),x=getint(),k=getint();
q[i]=(Query){v,x,k,i};
}
std::sort(&q[],&q[cnt_q]);
s.reset(n);
t.reset(n);
for(register int i=,p=;i<cnt_q;i++) {
while(p<m&&e[p].w<=q[i].x) add_edge(e[p++]);
ans[q[i].id]=t.query(t.root[s.find(q[i].v)],,tmp[],q[i].k);
}
for(register int i=;i<cnt_q;i++) {
printf("%d\n",~ans[i]?tmp[ans[i]]:-);
}
return ;
}
[ONTAK2010]Peaks的更多相关文章
- bzoj 3545&&3551: [ONTAK2010]Peaks &&加强版 平衡树&&并查集合并树&&主席树
3545: [ONTAK2010]Peaks Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 635 Solved: 177[Submit][Stat ...
- BZOJ 3545: [ONTAK2010]Peaks( BST + 启发式合并 + 并查集 )
这道题很好想, 离线, 按询问的x排序从小到大, 然后用并查集维护连通性, 用平衡树维护连通块的山的权值, 合并就用启发式合并.时间复杂度的话, 排序是O(mlogm + qlogq), 启发式合并是 ...
- BZOJ 3551: [ONTAK2010]Peaks加强版 [Kruskal重构树 dfs序 主席树]
3551: [ONTAK2010]Peaks加强版 题意:带权图,多组询问与一个点通过边权\(\le lim\)的边连通的点中点权k大值,强制在线 PoPoQQQ大爷题解传送门 说一下感受: 容易发现 ...
- BZOJ 3545: [ONTAK2010]Peaks [Splay启发式合并]
3545: [ONTAK2010]Peaks 题意:带权图,多组询问与一个点通过边权\(\le x\)的边连通的点中点权k大值 又读错题了,输出点一直WA,问的是点权啊 本题加强版强制在线了,那这道题 ...
- bzoj3545: [ONTAK2010]Peaks 重构树 主席树
题目链接 bzoj3545: [ONTAK2010]Peaks 题解 套路重构树上主席树 代码 #include<cstdio> #include<algorithm> #de ...
- 【BZOJ3545】 [ONTAK2010]Peaks
BZOJ3545 [ONTAK2010]Peaks Solution 既然会加强版,直接把强制在线的操作去掉就好了. 代码实现 #include<stdio.h> #include< ...
- 【BZOJ3551】 [ONTAK2010]Peaks加强版
BZOJ3551 [ONTAK2010]Peaks加强版 Solution Kruscal重构树后发现可以对于小于的离散化然后倍增+主席树找到上一个的可行解. 然后就可以了. 如果数组开的不好,容易在 ...
- [ONTAK2010]Peaks kruskal重构树,主席树
[ONTAK2010]Peaks kruskal重构树练手题. LG传送门竟然不强制在线?看到离线水过很不爽:B站强制在线版传送门 看到"询问从点\(v\)开始只经过困难值小于等于\(x\) ...
- bzoj 3545/3551: [ONTAK2010]Peaks -- 主席树,最小生成树,倍增
3545: [ONTAK2010]Peaks Time Limit: 10 Sec Memory Limit: 128 MB Description 在Bytemountains有N座山峰,每座山峰 ...
- 【BZOJ3551】[ONTAK2010]Peaks加强版 最小生成树+DFS序+主席树
[BZOJ3545][ONTAK2010]Peaks Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困 ...
随机推荐
- 我的Python分析成长之路6
模块:本质就是.py结尾的文件.从逻辑上组织python代码. 包: 本质就是一个目录,带有__init__.py文件,从逻辑上组织模块. 模块的分类: 1.标准库(内置的模块) 2.开源库(第三方库 ...
- BFS:UVa1590-IP Networks (子网掩码相关知识)
IP Networks Alex is administrator of IP networks. His clients have a bunch of individual IP addresse ...
- 最长回文子串——manacher
最长回文子串--Manacher 算法 (原版的博主的代码都是用py写的,这里改成c++) c++ 算法 字符串处理 0. 问题定义 最长回文子串问题:给定一个字符串,求它的最长回文子串长度. 如果一 ...
- Python中的并发
目录 Python并发 并发三种层次 协程 生成者消费者 新关键字 网络io 线/进程 例子 线程池 进程通信 并发池 future对象 executor对象 参考 Python并发 并发三种层次 个 ...
- 关于C#Debug和Release
在程序调试时的debug和release 网上有如下的描述:Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序.Release 称为发布版本,它往往是进行了各种优化,使 ...
- nuc 第二届山西省大学生程序设计大赛 魔力手环
problem 很妙啊--发现状态转移矩阵每一行都可以由上一行平移得到,每次只算第一行然后平移,\(O(n^3)\) 就变成了 \(O(n^2)\). #include <iostream> ...
- python学习-- {% csrf_token %}
1.不推荐禁用掉django中的CSRF. 2.我们可以再html页面的form表单中添加csrf_token,带着表单的请求一起发送到服务器去验证. <form enctype=" ...
- SDOJ 3696 Tree
描述 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有need条白色边的生成树. 题目保证有解. 输入 第一行V,E,need分别表示点数,边数和需要的白色边数. 接下来E行 每行 ...
- PHP 教父鸟哥 Yar 的原理分析
模块越来越多,业务越来越复杂,RPC 就上场了,在 PHP 的世界里,鸟哥的作品一直备受广大网友的青睐.下面一起学习下鸟哥的 PRC 框架 Yar . 揭开 Yar 神秘面纱 RPC 采用客户端/服务 ...
- NOJ——1508火烧赤壁2(并查集+启发式合并+逆序加边)
[1508] 火烧赤壁2 时间限制: 1000 ms 内存限制: 65535 K 问题描述 上次出了一道火烧赤壁的题目给当时的新生,也就是你们的上一届学长们做,那么这次,我又想到了另一个想法. 上次的 ...