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的更多相关文章

  1. 【bzoj3545】[ONTAK2010]Peaks 线段树合并

    [bzoj3545][ONTAK2010]Peaks 2014年8月26日3,1512 Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路 ...

  2. [BZOJ3545] [ONTAK2010]Peaks(线段树合并 + 离散化)

    传送门 由于困难值小于等于x这个很恶心,可以离线处理,将边权,和询问时的x排序. 每到一个询问的时候,将边权小于等于x的都合并起来再询问. .. 有重复元素的线段树合并的时间复杂度是nlog^2n # ...

  3. BZOJ.3545.[ONTAK2010]Peaks(线段树合并)

    题目链接 \(Description\) 有n个座山,其高度为hi.有m条带权双向边连接某些山.多次询问,每次询问从v出发 只经过边权<=x的边 所能到达的山中,第K高的是多少. \(Solut ...

  4. BZOJ3545 Peaks 离线处理+线段树合并

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

  5. bzoj3545 Peaks 线段树合并

    离线乱搞... 也就是一个线段树合并没什么 #include<algorithm> #include<iostream> #include<cstring> #in ...

  6. bzoj3545: [ONTAK2010]Peaks 重构树 主席树

    题目链接 bzoj3545: [ONTAK2010]Peaks 题解 套路重构树上主席树 代码 #include<cstdio> #include<algorithm> #de ...

  7. Peaks 线段树合并

    Peaks 线段树合并 \(n\)个带权值\(h_i\)山峰,有\(m\)条山峰间双向道路,\(q\)组询问,问从\(v_i\)开始只经过\(h_i\le x\)的路径所能到达的山峰中第\(k\)高的 ...

  8. 线段树合并&&启发式合并笔记

    这俩东西听起来很高端,实际上很好写,应用也很多~ 线段树合并 线段树合并,顾名思义,就是建立一棵新的线段树保存原有的两颗线段树的信息. 考虑如何合并,对于一个结点,如果两颗线段树都有此位置的结点,则直 ...

  9. bzoj3545 [ONTAK2010]Peaks、bzoj3551 [ONTAK2010]Peaks加强版

    题目描述: bzoj3545,luogu bzoj3551 题解: 重构树+线段树合并. 可以算是板子了吧. 代码(非强制在线): #include<cstdio> #include< ...

随机推荐

  1. SpringBoot2.0 基础案例(12):基于转账案例,演示事务管理操作

    本文源码 GitHub地址:知了一笑 https://github.com/cicadasmile/spring-boot-base 一.事务管理简介 1.事务基本概念 一组业务操作ABCD,要么全部 ...

  2. Jenkins+Git+Docker+K8s部署

    准备工作 Jenkins已安装 Docker和K8s部署运行成功 代码管理工具使用Git 最近公司项目使用Jenkins+Git+Docker+K8s进行持续化构建部署,这里笔者整理了一下构建部署的相 ...

  3. maven - 初识

    一.Maven是什么? Maven官网的描述:Apache Maven is a software project management and comprehension tool. Based o ...

  4. C 语言实例 - 判断奇数/偶数

    C 语言实例 - 判断奇数/偶数 C 语言实例 C 语言实例 以下实例判断用户输入的整数是奇数还是偶数. 实例 #include <stdio.h> int main() { int nu ...

  5. 4、CreateJS介绍-PreLoadJS

    需要在html5文件中引入的CreateJS库文件是preloadjs-0.4.1.min.js HTML5文件如下: <!DOCTYPE html> <html lang=&quo ...

  6. D、Homework of PE 容斥原理

    https://scut.online/p/113 终于想懂了这个容斥, 华工4月23号校赛,考虑总的所有情况,设1---n里面含有质数的个数为all,需要固定m个质数.那么有 totSum = C( ...

  7. RESTful API设计相关

    一  RESTful架构 在当今时代,越来越多人意识到了网站即软件. 这种"互联网软件"采用客户端/服务器模式,建立在分布式体系上,通过互联网通信,具有高延时(high laten ...

  8. Code First 2

    在codefirst一中也说了Mapping是实体与数据库的纽带,model通过Mapping映射到数据库,我们可以从数据库的角度来分析?首先是映射到数据库,这个是必须的.数据库里面一般包括表.列.约 ...

  9. (转)在Unity3D中控制动画播放

    用Unity3D也算是好久了,但是每次做项目总还是能学到新的东西.这次做一个TPS的项目就遇到了这样一个问题,如何同时在上下半身播放不同的动画?解决方法其实是很简单,但由于对于动画资源的了解不足导致问 ...

  10. 实例——省市区三级联动 & 还可以输入字符统计

    1 省市区三级联动 html代码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8" ...