【BZOJ3551】【洛谷P4197】—Peaks加强版(Kruscal重构树+主席树)
这道题有毒吧
洛谷,本机,然而上莫名??
无说
考虑到有多次询问瓶颈路
我们构建重构树
由于重构树特殊的性质
树上一个点的子树的权值必定都是比这个点小的
那么对于每次询问的,我们考虑找到它到根路径上第一个权值大于等于的点
这个可以用树上倍增实现
那现在的问题就变成了在一个点的子树中,查询所有叶子节点的第大
这个对于序中叶子节点建主席树就解决了
虽然感觉实现有点难写
不过有个小技巧:我们可以发现重构树上每个非叶节点必定有2个儿子
那么我们可以直接对每个点维护左右儿子,就不需要建邻接表
具体细节可以看代码(丑到窒息)
还有重构树可能是不连通的
这个情况要判断
#include<bits/stdc++.h>
using namespace std;
inline int read(){
char ch=getchar();
int res=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
return res*f;
}
const int N=500005;
const int M=1000005;
const int Log=22;
int n,m,q,h[N],s[N],ans=-1;
namespace Kruscal{
struct edge{
int u,v,w;
}e[N];
int adj[N<<1],nxt[M<<2],to[M<<2],val[N<<1],tot,cnt,lc[N<<1],rc[N<<1],f[N<<1][Log],fa[N];
inline bool comp(const edge &a,const edge &b){
return a.w<b.w;
}
inline void addedge(int u,int v){
nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v;
}
int find(int x){
return fa[x]==x?x:fa[x]=find(fa[x]);
}
inline void kruscal(){
sort(e+1,e+m+1,comp);
for(int i=1;i<=m;i++){
int f1=find(e[i].u),f2=find(e[i].v);
if(f1!=f2){
fa[f1]=fa[f2]=fa[++tot]=tot;
f[f1][0]=f[f2][0]=tot;
lc[tot]=f1,rc[tot]=f2;
val[tot]=e[i].w;
}
}
}
}
namespace JZMS_Tree{
#define mid ((l+r)>>1)
#define lc(u) son[u][0]
#define rc(u) son[u][1]
int rt[N<<3],sum[7000000],num,son[7000000][2];
void insert(int &u,int r1,int l,int r,int pos){
u=++num;
sum[u]=sum[r1]+1;
if(l==r)return;
lc(u)=lc(r1),rc(u)=rc(r1);
if(pos<=mid)insert(lc(u),lc(r1),l,mid,pos);
else insert(rc(u),rc(r1),mid+1,r,pos);
}
int query(int r1,int r2,int l,int r,int k){
if(l==r)return s[l];
int t=sum[rc(r1)]-sum[rc(r2)];
if(t>=k)return query(rc(r1),rc(r2),mid+1,r,k);
else return query(lc(r1),lc(r2),l,mid,k-t);
}
#undef lc
#undef rc
}
namespace Pre_operator{
using namespace Kruscal;
using namespace JZMS_Tree;
int in[N<<1],out[N<<1];
int dfn;
void dfs(int u){
for(int i=1;i<=20;i++)
f[u][i]=f[f[u][i-1]][i-1];
if(u<=n){
in[u]=out[u]=++dfn;
insert(rt[dfn],rt[dfn-1],1,n,h[u]);
return;
}
dfs(lc[u]),dfs(rc[u]);
in[u]=in[lc[u]],out[u]=out[rc[u]];
}
int get(int u,int k){
for(int i=20;i>=0;i--){
if(f[u][i]&&val[f[u][i]]<=k)
u=f[u][i];
}
return u;
}
}
using namespace Pre_operator;
int main(){
tot=n=read(),m=read(),q=read();
for(int i=1;i<=n;i++)h[i]=s[i]=read();
sort(s+1,s+n+1);
for(int i=1;i<=n;i++)
h[i]=lower_bound(s+1,s+n+1,h[i])-s;
for(int i=1;i<=m;i++){
e[i].u=read(),e[i].v=read(),e[i].w=read();
}
for(int i=1;i<=n;i++)fa[i]=i;
kruscal();
for(int i=tot;i;i--)
if(!in[i])dfs(i);
dfs(find(1));
for(int i=1;i<=q;i++){
int v=read(),x=read(),k=read();
if(ans!=-1)v^=ans,x^=ans,k^=ans;
v=get(v,x);
if(out[v]-in[v]+1<k)ans=-1;
else ans=query(rt[out[v]],rt[in[v]-1],1,n,k);
cout<<ans<<'\n';
}
}