P4197 Peaks kruskal 重构树
作者:互联网
这题有个加强版 是在线的
离线可以线段树合并 fhq合并(没试过后面这个)
在线的话得用新科技了 那就是kruskal重构树
先按最小生成树重构 然后就是一个大根堆
我们发现 v这个点向上找到的最后一个<=x的祖先
这个祖先的所有儿子 都是v在x的限制下可达的
然后就是主席树板子了(好久没写主席树。。)
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+100;
const int M = 5e5+100;
int n,m,q;
struct edge{
int u,v,w;
bool operator < (const edge&a)const{
return w<a.w;
}
}e[M];
int fa[N],h[N],hh,has[N],f[N][22],dep[N],val[N],cnt;
vector<int>to[N];
int st[N],ed[N];
int ls[N*30],rs[N*30],sum[N*30],rt[N],tot;
void add_edge(int x,int y){
to[x].push_back(y);
to[y].push_back(x);
}
int getfa(int x){
return fa[x]==x?x:fa[x]=getfa(fa[x]);
}
void update(int &o,int las,int l,int r,int pos){
o=++tot;
sum[o]=sum[las]+1;
if(l==r) return;
int mid = l+r>>1;
if(pos<=mid) rs[o]=rs[las],update(ls[o],ls[las],l,mid,pos);
else ls[o]=ls[las],update(rs[o],rs[las],mid+1,r,pos);
}
int query(int ql,int qr,int l,int r,int k){
if(l==r) return l;
int tt=sum[rs[qr]]-sum[rs[ql]],mid=l+r>>1;
//printf("l=%d r=%d tt=%d\n",l,r,tt);
if(k<=tt) return query(rs[ql],rs[qr],mid+1,r,k);
else return query(ls[ql],ls[qr],l,mid,k-tt);
}
void dfs(int u,int ff){
dep[u]=dep[ff]+1;
f[u][0]=ff;
st[u]=++cnt;
for(int i = 1; i <= 20; i++){
if(dep[u]<(1<<i)) break;
else f[u][i]=f[f[u][i-1]][i-1];
}
if(u<=n){
update(rt[st[u]],rt[st[u]-1],1,hh,h[u]);
}else{
rt[st[u]]=rt[st[u]-1];
}
for(auto v:to[u]){
if(v==ff) continue;
dfs(v,u);
}
ed[u]=cnt;
}
int main(){
val[0]=1e9+100;
scanf("%d%d%d",&n,&m,&q);
for(int i = 1; i <= n; i++)
scanf("%d",&h[i]),has[i]=h[i];
sort(has+1,has+1+n);
hh=unique(has+1,has+1+n)-has-1;
for(int i = 1; i <= n; i++)
h[i]=lower_bound(has+1,has+1+hh,h[i])-has;
for(int i = 1; i <= 2*n; i++) fa[i]=i;
for(int i = 1; i <= m; i++){
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
}
sort(e+1,e+1+m);
int id=n;
for(int i = 1; i <= m; i++){
int fu=getfa(e[i].u),fv=getfa(e[i].v);
if(fu!=fv){
fa[fu]=fa[fv]=++id;
val[id]=e[i].w;
add_edge(fu,id);
add_edge(fv,id);
}
}
for(int i = 1; i <= n; i++) if(!st[i]) dfs(getfa(i),0);
for(int i = 1; i <= q; i++){
int v,x,k;
scanf("%d%d%d",&v,&x,&k);
for(int i = 20; i >= 0; i--){
if(dep[v]<(1<<i)) continue;
if(val[f[v][i]]<=x) v=f[v][i];
}
if(sum[rt[ed[v]]]-sum[rt[st[v]-1]]<k){
puts("-1");
}else{
printf("%d\n",has[query(rt[st[v]-1],rt[ed[v]],1,hh,k)]);
}
}
return 0;
}
/*
4 3 100
1 2 3 4
1 2 8
2 4 1
1 3 4
1 8 2
*/
标签:return,Peaks,int,kruskal,fa,edge,P4197,const,sum 来源: https://www.cnblogs.com/League-of-cryer/p/14210301.html