Peaks 加强版-题解
Peaks 加强版(强制在线版)-题解
题面
在有 -1。
算法标签
-
Kruskal 重构树
-
可持久化线段树(主席树)
-
倍增
-
离散化
题目分析
寻找只经过困难值小于等于
我们从点
实现细节
按照 Kruskal 重构出来的 dfs 序建立主席树,记录每个节点子树管辖范围的开始对应根节点和结束对应根节点。原图中的节点在重构的树中全是叶子节点,所以插入操作只在叶子节点存在。接着就是主席树求第
完整代码
#include<bits/stdc++.h>
#define Int long long int
#define Tem template
#define Pub public
using std::min;using std::max;
int n,m,q;
Int h[100005];
Int num[100005],newn;//对h的需离散化
class Edge{//边
Pub:int a,b;Int c;
}e[500005];
class HJT{//主席树
Pub:int size;
int ls,rs;
}t[5000000];
int root[100005];
int cnt_HJT;
int ins(int RT,int L,int R,int x){//主席树插入
int rt=++cnt_HJT;
t[rt]=t[RT];
++t[rt].size;
if(L<R){
int M=(L+R)/2;
if(x<=M)
t[rt].ls=ins(t[RT].ls,L,M,x);
else
t[rt].rs=ins(t[RT].rs,M+1,R,x);
}
return rt;
}
int kth(int RT1,int RT2,int L,int R,int k){//主席树查询
if(t[RT2].size-t[RT1].size<k)return -1;
if(L==R)return L|R;
int M=(L+R)/2;
if(t[t[RT2].rs].size-t[t[RT1].rs].size>=k)
return kth(t[RT1].rs,t[RT2].rs,M+1,R,k);
else
return kth(t[RT1].ls,t[RT2].ls,L,M,k-(t[t[RT2].rs].size-t[t[RT1].rs].size));
}
class Node{//重构树的节点
Pub:Int c[20],cc;
int ls,rs,fa[20];
int boss;
int lrt,rrt;
}d[200005];
int cnt_node;
int Boss(int x){//并查集路径压缩
if(d[x].boss!=x)d[x].boss=Boss(d[x].boss);
return d[x].boss;
}
void Merge(int x,int y,Int c){//并查集合并与重构树新建节点
x=Boss(x),y=Boss(y);
if(x==y)return;
d[x].fa[0]=d[x].boss=d[y].fa[0]=d[y].boss=++cnt_node;
d[x].c[0]=d[y].c[0]=c;
d[cnt_node].boss=cnt_node;
d[cnt_node].cc=c;
d[cnt_node].ls=x;d[cnt_node].rs=y;
}
void kruskal(){//Kruskal重构树
for(int i=1;i<=n;++i)d[i].boss=i;
std::sort(e+1,e+1+m,[](Edge a,Edge b)->bool{return a.c<b.c;});
for(int i=1;i<=m;++i)
Merge(e[i].a,e[i].b,e[i].c);
}
int cnt_rt;
void dfs(int x){//倍增预处理
if(x==0)return;
d[x].lrt=cnt_rt;
for(int i=1;i<=18;++i){
d[x].fa[i]=d[d[x].fa[i-1]].fa[i-1];
d[x].c[i]=max(d[x].c[i-1],d[d[x].fa[i-1]].c[i-1]);
}
if(x<=n){
root[cnt_rt+1]=ins(root[cnt_rt],1,newn,h[x]);
++cnt_rt;
}
dfs(d[x].ls);dfs(d[x].rs);
d[x].rrt=cnt_rt;
}
int lastans;
void query(int st,Int x,int k){//查询
for(int i=18;i>=0;--i)
if(d[st].c[i]<=x&&d[st].fa[i])
st=d[st].fa[i];
int ans;
if(d[st].cc>x)ans=-1;
else ans=kth(root[d[st].lrt],root[d[st].rrt],1,newn,k);
if(ans==-1)printf("-1\n"),lastans=0;
else printf("%lld\n",num[ans]),lastans=num[ans];
}
int main(){
scanf("%d%d%d",&n,&m,&q);
cnt_node=n;
for(int i=1;i<=n;++i){
scanf("%lld",&h[i]);
num[i]=h[i];
}
std::sort(num+1,num+1+n);
newn=std::unique(num+1,num+1+n)-num-1;
for(int i=1;i<=n;++i)
h[i]=std::lower_bound(num+1,num+1+newn,h[i])-num;
for(int i=1;i<=m;++i)
scanf("%d%d%lld",&e[i].a,&e[i].b,&e[i].c);
kruskal();
dfs(cnt_node);
while(~--q){
int st;Int x;int k;
scanf("%d%lld%d",&st,&x,&k);//注意强制在线的转换
st=st^lastans;
x=x^lastans;
k=k^lastans;
query(st,x,k);
}
return 0;
}