LG P4197 Peaks/BZOJ3551 [ONTAK2010]Peaks加强版
Description
在 Bytemountains 有 $n$ 座山峰,每座山峰有他的高度 $h_i$。有些山峰之间有双向道路相连,共 $m$ 条路径,每条路径有一个困难值,这个值越大表示越难走。
现在有 $q$ 组询问,每组询问询问从点 $v$ 开始只经过困难值小于等于 $x$ 的路径所能到达的山峰中第 $k$ 高的山峰,如果无解输出 $-1$。
Solution
kruskal重构树后,由点$x$可以到达的,经过边权小于$k$的构成一个包含$x$的子树,可以倍增找到子树的根
转化为一个子树内的第$k$大,可以再转化到DFS序上区间第$k$大
主席树干就完了
两个题的区别在于是否强制在线
#include<algorithm> #include<iostream> #include<cstdio> using namespace std; int n,m,q,val[200005],sav[200005],N,f[200005],head[200005],tot,fa[200005][21],in[200005],out[200005],idx,lasans; bool vst[200005]; struct Node{ int x,y,w; bool operator <(const Node &z)const{return w<z.w;} }node[500005]; struct Edge{ int to,nxt; }edge[500005]; namespace SGT{ int cnt,rt[200005],ls[4000005],rs[4000005],sum[4000005]; int update(int i,int l,int r,int p){ int k=++cnt,mid=l+r>>1; ls[k]=ls[i],rs[k]=rs[i],sum[k]=sum[i]+1; if(l==r)return k; if(p<=mid)ls[k]=update(ls[i],l,mid,p); else rs[k]=update(rs[i],mid+1,r,p); return k; } int query(int u,int v,int l,int r,int k){ if(l==r)return l; int mid=l+r>>1,s=sum[rs[v]]-sum[rs[u]]; if(s>=k)return query(rs[u],rs[v],mid+1,r,k); else return query(ls[u],ls[v],l,mid,k-s); } } inline int read(){ int f=1,w=0; char ch=0; while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=getchar(); return f*w; } int find(int x){return f[x]==x?x:f[x]=find(f[x]);} void addedge(int u,int v){edge[++tot]=(Edge){v,head[u]},head[u]=tot;} void Exkruskal(){ int cnt=n; sort(node+1,node+m+1); for(int i=1;i<=m;i++){ int fx=find(node[i].x),fy=find(node[i].y); if(fx!=fy){ val[++cnt]=node[i].w,f[fx]=cnt,f[fy]=cnt,addedge(cnt,fx),addedge(cnt,fy); if(cnt==2*n-1)break; } } } void dfs(int k,int f){ fa[k][0]=f,in[k]=++idx,vst[k]=true; for(int i=1;i<=20;i++)fa[k][i]=fa[fa[k][i-1]][i-1]; if(k<=n)SGT::rt[idx]=SGT::update(SGT::rt[idx-1],1,N,val[k]); else SGT::rt[idx]=SGT::rt[idx-1]; for(int i=head[k];i;i=edge[i].nxt){ int v=edge[i].to; dfs(v,k); } out[k]=idx; } int findpos(int x,int lim){ for(int i=20;~i;i--)if(val[fa[x][i]]<=lim)x=fa[x][i]; return x; } int main(){ n=read(),m=read(),q=read(),val[0]=0x7f7f7f7f; for(int i=1;i<=n;i++)sav[i]=val[i]=read(); sort(sav+1,sav+n+1),N=unique(sav+1,sav+n+1)-sav-1; for(int i=1;i<=n;i++)val[i]=lower_bound(sav+1,sav+N+1,val[i])-sav; for(int i=1;i<=m;i++)node[i]=(Node){read(),read(),read()}; for(int i=1;i<=2*n;i++)f[i]=i; Exkruskal(); for(int i=1;i<=n;i++)if(!vst[i])dfs(find(i),0); // for(int i=1;i<=n*2-1;i++)cout<<fa[i][2]<<" "; for(;q;q--){ int v=read(),x=read(),k=read(); int pos=findpos(v,x); // cout<<SGT::sum[SGT::rt[out[pos]]]<<" "; if(SGT::sum[SGT::rt[out[pos]]]-SGT::sum[SGT::rt[in[pos]-1]]<k)lasans=-1; else lasans=sav[SGT::query(SGT::rt[in[pos]-1],SGT::rt[out[pos]],1,N,k)]; printf("%d\n",lasans); } return 0; }