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

【bzoj3545】[ONTAK2010]Peaks

2014年8月26日3,1512

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

对于每组询问,输出一个整数表示答案。

Sample Input

10 11 4
1 2 3 4 5 6 7 8 9 10
1 4 4
2 5 3
9 8 2
7 8 10
7 1 4
6 7 1
6 4 8
2 1 5
10 8 10
3 4 7
3 4 6
1 5 2
1 5 6
1 5 8
8 9 2

Sample Output

6
1
-1
8

HINT

【数据范围】
N<=10^5, M,Q<=5*10^5,h_i,c,x<=10^9。

题解

  离散后排序,维护加边顺序,然后就是线段树合并了,权值线段树。

  1 #include<cstring>
  2 #include<cmath>
  3 #include<algorithm>
  4 #include<iostream>
  5 #include<cstdio>
  6
  7 #define N 100007
  8 #define M 500007
  9 #define ll long long
 10 using namespace std;
 11 inline int read()
 12 {
 13     int x=0,f=1;char ch=getchar();
 14     while(ch>‘9‘||ch<‘0‘){if (ch==‘-‘) f=-1;ch=getchar();}
 15     while(ch<=‘9‘&&ch>=‘0‘){x=(x<<3)+(x<<1)+ch-‘0‘;ch=getchar();}
 16     return x*f;
 17 }
 18
 19 int n,m,q,sz;
 20 int fa[N],rt[N],ans[M],disc[N],h[N];
 21 int siz[M*10],ls[M*10],rs[M*10];
 22 struct Node
 23 {
 24     int x,y,difficulty;
 25 }a[M];
 26 struct Date
 27 {
 28     int x,limit,k,id;
 29 }b[M];
 30
 31 int find(int num)
 32 {
 33     if (fa[num]!=num) fa[num]=find(fa[num]);
 34     return fa[num];
 35 }
 36 bool cmp(Node x,Node y)
 37 {
 38     return x.difficulty<y.difficulty;
 39 }
 40 bool cmp1(Date x,Date y)
 41 {
 42     return x.limit<y.limit;
 43 }
 44
 45 int merge(int x,int y)
 46 {
 47     if (!x)return y;
 48     if (!y)return x;
 49     if (!ls[x]&&!rs[x])
 50     {
 51         siz[x]=siz[x]+siz[y];
 52         return x;
 53     }
 54     ls[x]=merge(ls[x],ls[y]);
 55     rs[x]=merge(rs[x],rs[y]);
 56     siz[x]=siz[ls[x]]+siz[rs[x]];
 57     return x;
 58 }
 59 void ins(int &p,int l,int r,int z)
 60 {
 61     if (!p)p=++sz,siz[p]=1;
 62     if (l==r) return;
 63     int mid=(l+r)>>1;
 64     if (z<=mid)ins(ls[p],l,mid,z);
 65     else ins(rs[p],mid+1,r,z);
 66 }
 67 int query(int p,int l,int r,int rank)
 68 {
 69     if (l==r) return l;
 70     int mid=(l+r)>>1;
 71     if (rank<=siz[ls[p]])return query(ls[p],l,mid,rank);
 72     else return query(rs[p],mid+1,r,rank-siz[ls[p]]);
 73 }
 74 void solve()
 75 {
 76     int now=0;
 77     for (int i=1;i<=q;i++)
 78     {
 79         while(now<m&&a[now+1].difficulty<=b[i].limit)
 80         {
 81             int x=find(a[now+1].x),y=find(a[now+1].y);
 82             if (x!=y)
 83             {
 84                 fa[y]=x;
 85                 rt[x]=merge(rt[x],rt[y]);
 86             }
 87             now++;
 88         }
 89         int x=find(b[i].x);
 90         if (siz[rt[x]]<b[i].k) ans[b[i].id]=-1;
 91         else ans[b[i].id]=disc[query(rt[x],1,n,siz[rt[x]]-b[i].k+1)];
 92     }
 93     for (int i=1;i<=q;i++)
 94         printf("%d\n",ans[i]);
 95 }
 96 int main()
 97 {
 98     freopen("fzy.in","r",stdin);
 99     freopen("fzy.out","w",stdout);
100
101     n=read(),m=read(),q=read();
102     for (int i=1;i<=n;i++)
103         disc[i]=h[i]=read(),fa[i]=i;
104     sort(disc+1,disc+n+1);
105     for (int i=1;i<=n;i++)
106         h[i]=lower_bound(disc+1,disc+n+1,h[i])-disc;
107     for (int i=1;i<=n;i++)
108         ins(rt[i],1,n,h[i]);
109
110     for (int i=1;i<=m;i++)
111         a[i].x=read(),a[i].y=read(),a[i].difficulty=read();
112     sort(a+1,a+m+1,cmp);
113     for (int i=1;i<=q;i++)
114         b[i].x=read(),b[i].limit=read(),b[i].k=read(),b[i].id=i;
115     sort(b+1,b+q+1,cmp1);
116     solve();
117 }

原文地址:https://www.cnblogs.com/fengzhiyuan/p/8142979.html

时间: 2024-10-14 13:50:16

【bzoj3545】[ONTAK2010]Peaks 线段树合并的相关文章

bzoj3545: [ONTAK2010]Peaks 主席树合并

排序以后,做并茶几+主席树合并维护,Orzstdcall,没想到权值线段树的合并竟然是O(nlogn)的...虽然他给我证明了一波,但是还是不是十分理解...听说是Cydiater给他讲的,Orz #include<bits/stdc++.h> using namespace std; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getcha

bzoj3545 Peaks 线段树合并

离线乱搞... 也就是一个线段树合并没什么 #include<algorithm> #include<iostream> #include<cstring> #include<cstdio> using namespace std; int n,m,q,tot,cnt,num,h[100001],a[100001],ans[500001],fa[100001],root[100001]; struct edge{ int u,v,cost; bool ope

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

传送门 由于困难值小于等于x这个很恶心,可以离线处理,将边权,和询问时的x排序. 每到一个询问的时候,将边权小于等于x的都合并起来再询问. .. 有重复元素的线段树合并的时间复杂度是nlog^2n #include <cstdio> #include <iostream> #include <algorithm> #define N 500001 int n, m, q, cnt, tot, size; int sum[N * 10], ls[N * 10], rs[N

【线段树合并】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,表示一组询问. Outpu

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

题目描述: bzoj3545,luogu bzoj3551 题解: 重构树+线段树合并. 可以算是板子了吧. 代码(强制在线): #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 100050; const int M = 5*N; template<typename T> inline void read(T&x) {

【BZOJ4399】魔法少女LJJ 线段树合并

[BZOJ4399]魔法少女LJJ Description 在森林中见过会动的树,在沙漠中见过会动的仙人掌过后,魔法少女LJJ已经觉得自己见过世界上的所有稀奇古怪的事情了LJJ感叹道“这里真是个迷人的绿色世界,空气清新.淡雅,到处散发着醉人的奶浆味:小猴在枝头悠来荡去,好不自在:各式各样的鲜花争相开放,各种树枝的枝头挂满沉甸甸的野果:鸟儿的歌声婉转动听,小河里飘着落下的花瓣真是人间仙境”SHY觉得LJJ还是太naive,一天,SHY带着自己心爱的图找到LJJ,对LJJ说:“既然你已经见识过动态树

【BZOJ2733】永无乡[splay启发式合并or线段树合并]

题目大意:给你一些点,修改是在在两个点之间连一条无向边,查询时求某个点能走到的点中重要度第k大的点.题目中给定的是每个节点的排名,所以实际上是求第k小:题目求的是编号,不是重要度的排名.我一开始差点被这坑了. 网址:http://www.lydsy.com/JudgeOnline/problem.php?id=2733 这道题似乎挺经典的(至少我看许多神犇很早就做了这道题).这道题有两种写法:并查集+(splay启发式合并or线段树合并).我写的是线段树合并,因为--splay不会打+懒得学.

BZOJ 4756 线段树合并(线段树)

思路: 1.最裸的线段树合并 2. 我们可以观察到子树求一个东西 那我们直接DFS序好了 入队的时候统计一下有多少比他大的 出的时候统计一下 减一下 搞定~ 线段树合并代码: //By SiriusRen #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N=100050; int n,col[N],cpy[N],tree[N*100],lso

bzoj2733: [HNOI2012]永无乡(splay+启发式合并/线段树合并)

这题之前写过线段树合并,今天复习Splay的时候想起这题,打算写一次Splay+启发式合并. 好爽!!! 写了长长的代码(其实也不长),只凭着下午的一点记忆(没背板子...),调了好久好久,过了样例,submit,1A! 哇真的舒服 调试输出懒得删了QwQ #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<queue> #include