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. maven - 初识

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

  2. CF438D The Child and Sequence 线段树

    给定数列,区间查询和,区间取模,单点修改. n,m小于10^5 ...当区间最值小于模数时,就直接返回就好啦~ #include<cstdio> #include<iostream& ...

  3. Java 2 个 List 集合数据求并、补集操作

    开发过程中,我们可能需要对 2 个 或多个 List 集合中的数据进行处理,比如多个 List 集合数据求 相同元素,多个 List 集合数据得到只属于本身的数据,如图示: 这里写图片描述 这里以 2 ...

  4. VS2010/OpenGL配置

    1.下载glut:http://www.opengl.org/resources/libraries/glut/glutdlls37beta.zip 2.把解压得到的glut.h放到"C:\ ...

  5. java的三大特性之一多态概述

    多态---概念 所谓多态就是一个引用在不同情况下的多种状态.多态是指通过指向父亲的指针,来调用在不同的子类中实现的方法. 多态---注意事项 00.java允许父类的引用变量引用它的子类的实例(对象) ...

  6. html学习笔记-XML

    html学习笔记-XML Table of Contents 1. XML简介 2. XML用途 3. XML树结构 4. XML语法 5. XML元素 6. XML属性 7. XML验证 8. XM ...

  7. 访问权限修饰符-static-final-this-super-匿名对象

    1.this关键字的作用     1)调用本类中的属性;     2)调用本类中的构造方法;且只能放首行,且必须留一个构造方法作为出口,即不能递归调用     3)表示当前对象; 2.匿名对象     ...

  8. Google Chrome 浏览器的备用(离线)安装程序

    Google Chrome 浏览器的备用(离线)安装程序(适用于 Windows) 如果您在使用 http://www.google.com/chrome 上的标准安装程序下载 Chrome 浏览器时 ...

  9. apple-touch-icon-precomposed

    <link rel="apple-touch-icon-precomposed" href=""> apple-touch-icon-precomp ...

  10. freebsd快速删除磁盘数据

    At the start, mark all system disks as empty. Repeat the following command for each hard drive: dd i ...