【线段树合并】bzoj3545: [ONTAK2010]Peaks
1A还行
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
对于每组询问,输出一个整数表示答案。
HINT
【数据范围】
N<=10^5, M,Q<=5*10^5,h_i,c,x<=10^9。
题目分析
题目所求的是“小于等于x的边”所成连通块中的第k大,这里就会自然想到处理这一类连通块问题的策略:从小到大加边维护连通块,并在这个过程中离线处理查询。
现在要维护的连通块信息是无序的集合,于是第一反应就是用set合并。但是显而易见的是,set不能处理第k大问题(话说暑假做“不等式组”那题时候第一反应就是用multiset处理,但是当时被查询key和第k大困扰了很久)。有一种常见的方法是采用权值线段树实现set的功能,这样一来就可以处理一些基础的查询问题。
处理完了连通块和维护的操作,接下去的问题就是合并。权值线段树本质上还是线段树,所以使用线段树合并的套路就可以保证这一部分的复杂度。
感觉是比较套路和数据结构的题,好像没什么营养……
#include<bits/stdc++.h>
const int maxn = ;
const int maxq = ;
const int maxm = ;
const int maxNode = ; struct node
{
int l,r,val;
}a[maxNode];
struct QRs
{
int v,x,k,id;
bool operator < (QRs a) const
{
return x < a.x;
}
}qr[maxq];
struct Edge
{
int u,v,val;
Edge(int a=, int b=, int c=):u(a),v(b),val(c) {}
bool operator < (Edge a) const
{
return val < a.val;
}
}edges[maxm];
int n,m,q,dal,tot,ans[maxq];
int fat[maxn],h[maxn],cnt[maxn],rt[maxn]; int read()
{
char ch = getchar();
int num = , fl = ;
for (; !isdigit(ch); ch=getchar())
if (ch=='-') fl = -;
for (; isdigit(ch); ch=getchar())
num = (num<<)+(num<<)+ch-;
return num*fl;
}
int find(int x){return x==fat[x]?x:fat[x]=find(fat[x]);}
int query(int rt, int l, int r, int c)
{
if (l==r) return l;
int mid = (l+r)>>;
if (c <= a[a[rt].l].val)
return query(a[rt].l, l, mid, c);
return query(a[rt].r, mid+, r, c-a[a[rt].l].val);
}
int queryPos(int v, int k)
{
int anc = find(v);
if (a[rt[anc]].val < k) return -;
return cnt[query(rt[anc], , cnt[], a[rt[anc]].val-k+)];
}
void update(int &rt, int l, int r, int c)
{
if (!rt) rt = ++tot;
++a[rt].val;
if (l==r) return;
int mid = (l+r)>>;
if (c <= mid) update(a[rt].l, l, mid, c);
else update(a[rt].r, mid+, r, c);
}
void merge(int &u, int v)
{
if (u*v==){
u = u?u:v;
return;
}
a[u].val += a[v].val;
merge(a[u].l, a[v].l);
merge(a[u].r, a[v].r);
}
int main()
{
n = read(), m = read(), q = read();
for (int i=; i<=n; i++) h[i] = cnt[i] = read(), fat[i] = i;
for (int i=; i<=m; i++)
edges[i].u = read(), edges[i].v = read(), edges[i].val = read();
for (int i=; i<=q; i++)
qr[i].v = read(), qr[i].x = read(), qr[i].k = read(), qr[i].id = i;
std::sort(edges+, edges+m+);
std::sort(cnt+, cnt+n+);
std::sort(qr+, qr+q+);
cnt[] = std::unique(cnt+, cnt+n+)-cnt-;
for (int i=; i<=n; i++)
{
h[i] = std::lower_bound(cnt+, cnt+cnt[]+, h[i])-cnt;
update(rt[i], , cnt[], h[i]);
}
dal = ;
for (int i=; i<=m; i++)
{
int fu = find(edges[i].u), fv = find(edges[i].v);
if (fu!=fv){
for (; dal<=q&&qr[dal].x < edges[i].val; ++dal)
ans[qr[dal].id] = queryPos(qr[dal].v, qr[dal].k);
fat[fu] = fv, merge(rt[fv], rt[fu]);
}
}
for (int i=dal; i<=q; i++)
ans[qr[i].id] = queryPos(qr[i].v, qr[i].k);
for (int i=; i<=q; i++) printf("%d\n",ans[i]);
return ;
}
END
【线段树合并】bzoj3545: [ONTAK2010]Peaks的更多相关文章
- 【bzoj3545】[ONTAK2010]Peaks 线段树合并
[bzoj3545][ONTAK2010]Peaks 2014年8月26日3,1512 Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路 ...
- [BZOJ3545] [ONTAK2010]Peaks(线段树合并 + 离散化)
传送门 由于困难值小于等于x这个很恶心,可以离线处理,将边权,和询问时的x排序. 每到一个询问的时候,将边权小于等于x的都合并起来再询问. .. 有重复元素的线段树合并的时间复杂度是nlog^2n # ...
- BZOJ.3545.[ONTAK2010]Peaks(线段树合并)
题目链接 \(Description\) 有n个座山,其高度为hi.有m条带权双向边连接某些山.多次询问,每次询问从v出发 只经过边权<=x的边 所能到达的山中,第K高的是多少. \(Solut ...
- BZOJ3545 Peaks 离线处理+线段树合并
题意: 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经 ...
- bzoj3545 Peaks 线段树合并
离线乱搞... 也就是一个线段树合并没什么 #include<algorithm> #include<iostream> #include<cstring> #in ...
- bzoj3545: [ONTAK2010]Peaks 重构树 主席树
题目链接 bzoj3545: [ONTAK2010]Peaks 题解 套路重构树上主席树 代码 #include<cstdio> #include<algorithm> #de ...
- Peaks 线段树合并
Peaks 线段树合并 \(n\)个带权值\(h_i\)山峰,有\(m\)条山峰间双向道路,\(q\)组询问,问从\(v_i\)开始只经过\(h_i\le x\)的路径所能到达的山峰中第\(k\)高的 ...
- 线段树合并&&启发式合并笔记
这俩东西听起来很高端,实际上很好写,应用也很多~ 线段树合并 线段树合并,顾名思义,就是建立一棵新的线段树保存原有的两颗线段树的信息. 考虑如何合并,对于一个结点,如果两颗线段树都有此位置的结点,则直 ...
- bzoj3545 [ONTAK2010]Peaks、bzoj3551 [ONTAK2010]Peaks加强版
题目描述: bzoj3545,luogu bzoj3551 题解: 重构树+线段树合并. 可以算是板子了吧. 代码(非强制在线): #include<cstdio> #include< ...
随机推荐
- SpringMVC 的数据绑定
1.数据自动绑定 SpringMVC 框架支持不需要任何数据绑定的注解直接将表单参数绑定到我们的执行方法的参数上. 表单参数:包括 POST 以及 GET 发送过来的参数 就是以内容类型为:encty ...
- 11.联结表---SQL
说明:使用交互式DBMS工具重要的是,要理解联结不是物理实体.换句话说,它在实际的数据库表中并不存在.DBMS会根据需要建立联结,它在查询执行期间一直存在. 一.等值语法:SELECT 字段 FROM ...
- loj6198谢特 后缀数组+并查集+Trie
先把问题放在后缀数组上考虑 已知两个数组a b,求min(a[i],...,a[j])+(b[i]^b[j])的最大值 套路题 初始每个点都是一个小连通块 把a按从大到小的顺序加入,计算当前加入边作为 ...
- response.setContentType() 作用及参数用法
笔者感冒了,转载大神的 https://blog.csdn.net/luman1991/article/details/53423305 下载中设置文件名称 https://blog.csdn.net ...
- 078 Subsets 子集
给定一组不同的整数 nums,返回所有可能的子集(幂集).注意事项:该解决方案集不能包含重复的子集.例如,如果 nums = [1,2,3],结果为以下答案:[ [3], [1], [2], ...
- nginx一个简单的反向代理设置
location /aaaaa/ { proxy_pass http://localhost:8080/aaaaa/; } 经过配置,现在访问 http://localhost/aaaaa/ 就会 ...
- CSS属性、伪类选择器,CSS3选择器
CSS1时IE6是部分支持,伟大的IE6!CSS2时IE6部分支持,伟大的IE6依旧是部分支持!CCS3盛行CSS4也已经提上日程的现在,IE6完全不支持.IE6你该走了,我们会永远记住你的功绩的!I ...
- 洛谷-P3927 SAC E#1 - 一道中档题 Factorial
原址 题目背景 数据已修改 SOL君(炉石主播)和SOL菌(完美信息教室讲师)是好朋友. 题目描述 SOL君很喜欢阶乘.而SOL菌很喜欢研究进制. 这一天,SOL君跟SOL菌炫技,随口算出了n的阶乘. ...
- C# 對 List<string> 取交集、補集、超集、串聯
List<string> ls1 =new List<string> { "a", "b", "c", " ...
- hystrix 给方法加断路器
添加依赖 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>s ...