传送门
没权限号可以来这里交,老规矩,不准说。
题面
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。
题解
首先,这个题有一个比较明显的做法,就是离线处理。
我们把边按权值排序,然后不断加入边,处理询问,加边的时候可以启发式合并。
然后时间复杂度就是
O(nlog2n)
了。
然后就有了另一个题:bzoj3551 peaks加强版(强制在线)
这个我也是才学,不会讲,还是放po姐的博客吧:
http://blog.csdn.net/PoPoQQQ/article/details/41348785
那个图就是样例输入的重构树,大家可以自己模拟一下它是如何建出来的。
还有,那几个性质好好想一想。
然后应该就懂了,po姐还是讲得很好的。
过程:
1.读入
2.离散化
3.做kruskal,同时构造出重构树
4.在kruskal重构树上dfs一遍,然后找出dfs序(只有叶子)和每个节点的子树中的叶子数量,以及每个点的子树在dfs序上的起始位置
5.在dfs序上建主席树
6.利用kruskal重构树的性质,我们只需要在dfs时处理出来每个点向上跳2^j步的位置,然后倍增地去跳到权值<=限制权值的深度最小的点,它的子树就是限制下可以到达的所有节点。
7.对于查询,我们在主席树上利用之前的信息直接查询即可。
跑得好慢
分别是9632ms(3545),17124ms(3551)
都是卡线呀(滑稽)
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<vector>
#include<queue>
#define ll long long
using namespace std;
inline int read(){
int x=0,f=1;char ch=' ';
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-48,ch=getchar();
return x*f;
}
const int N=1e5+500;
const int M=5e5+500;
struct kedge{
int x,y,l;
inline bool operator < (const kedge& b) const {return l<b.l;}
}e[M];
struct edge{
int to,next;
}e1[M<<1],e2[M+N];
int n,m,q,tot1,tot2,tot,hash_cnt;
int h[N],fa[N+M],head1[N],head2[N+M],w[N+M],dep[N+M],b[N];
inline void addedge1(int x,int y){e1[++tot1].to=y;e1[tot1].next=head1[x];head1[x]=tot1;}
inline void addedge2(int x,int y){e2[++tot2].to=y;e2[tot2].next=head2[x];head2[x]=tot2;}
inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
inline void kruskal(){
for(int i=1;i<=n;i++)fa[i]=i,w[i]=h[i];
sort(e+1,e+m+1);tot=n;int j=n;
for(int i=1;i<=m;i++){
int x=e[i].x;int y=e[i].y;int l=e[i].l;
int u=find(x);int v=find(y);
if(u==v)continue;
w[++tot]=l;
addedge2(tot,u);addedge2(tot,v);
fa[u]=fa[v]=fa[tot]=tot;
j--;if(j==1)break;
}
}
struct node{
int ls,rs,size;
}t[N*25];
int st[20][N+M],size[N+M],dfn[N+M],dfn_clock,cnt,root[N+M],mp[N+M],start[N+M];
inline void dfs(int x){
for(int k=1;k<=19&&(1<<k)<=dep[x];k++){
st[k][x]=st[k-1][st[k-1][x]];
}
size[x]=0;start[x]=dfn_clock+1;
if(x<=n)dfn[++dfn_clock]=x,size[x]++,mp[x]=dfn_clock;
for(int i=head2[x];i;i=e2[i].next){
int u=e2[i].to;
st[0][u]=x;dep[u]=dep[x]+1;
dfs(u);
size[x]+=size[u];
}
}
inline void build(int &now,int l,int r){
now=++cnt;
if(l==r)return;
int mid=(l+r)>>1;
build(t[now].ls,l,mid);
build(t[now].rs,mid+1,r);
}
inline void insert(int &now,int pre,int l,int r,int x){
now=++cnt;
t[now]=t[pre];
t[now].size++;
if(l==r)return;
int mid=(l+r)>>1;
if(x<=mid)insert(t[now].ls,t[pre].ls,l,mid,x);
else insert(t[now].rs,t[pre].rs,mid+1,r,x);
}
inline int kth(int now,int pre,int l,int r,int k){
if(l==r){
if(k>t[now].size-t[pre].size)return -1;
else return b[l];
}
int rsize=t[t[now].rs].size-t[t[pre].rs].size;
int mid=(l+r)>>1;
if(k<=rsize)return kth(t[now].rs,t[pre].rs,mid+1,r,k);
else return kth(t[now].ls,t[pre].ls,l,mid,k-rsize);
}
inline void make(){
build(root[0],1,hash_cnt);
for(int i=1;i<=dfn_clock;i++){
h[dfn[i]]=lower_bound(b+1,b+hash_cnt+1,h[dfn[i]])-b;
insert(root[i],root[i-1],1,hash_cnt,h[dfn[i]]);
}
}
inline int jump(int x,int V){
for(int k=19;k>=0;k--){
if(st[k][x]&&w[st[k][x]]<=V){
x=st[k][x];
}
}
return x;
}
int main(){
n=read();m=read();q=read();
for(int i=1;i<=n;i++)h[i]=read(),b[i]=h[i];
sort(b+1,b+n+1);
hash_cnt=unique(b+1,b+n+1)-b-1;
for(int i=1;i<=m;i++){
int x=read(),y=read(),l=read();
addedge1(x,y);addedge1(y,x);
e[i].x=x;e[i].y=y;e[i].l=l;
}
kruskal();
dep[tot]=1;
dfs(tot);
make();
int lastans=0;
while(q--){
int x=read()^lastans,V=read()^lastans,k=read()^lastans;
int top=jump(x,V);
lastans=kth(root[start[top]+size[top]-1],root[start[top]-1],1,hash_cnt,k);
printf("%d\n",lastans);
if(lastans==-1)lastans=0;
}
return 0;
}