萌新刚学OI,离线+并查集+线段树合并成功TLE,感觉复杂度没问题,请各位大神帮忙看一下。
#include<bits/stdc++.h>
using namespace std;
int n,m,q,nn;
int h[5000001],hb[5000001],rt[5000001],tot;
int f[5000001],ans[5000001];
inline void read(int &res){
res = 0;
int f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if(ch == '-') f = -1;
ch = getchar();
}
while('0' <= ch && ch <= '9'){
res = (res << 1) + (res << 3) + (ch - 48);
ch = getchar();
}
res *= f;
}
struct edge{
int u,v,w;
}e[5000001];
struct ques{
int id,u,w,k;
}prob[5000001];
struct node{
int ls,rs,sum,cnt;
}t[50000001];
inline bool cmp(edge a,edge b){
return a.w<b.w;
}
inline bool cmp2(ques a,ques b){
return a.w<b.w;
}
inline void insert(int &u,int l,int r,int p){
if(!u)u=++tot;
t[u].sum++;
if(l==r)return;
int mid=(l+r)>>1;
if(p<=mid)insert(t[u].ls,l,mid,p);
else insert(t[u].rs,mid+1,r,p);
}
inline void merge(int &rt1,int rt2){
if(!rt2)return;
if(!rt1){
rt1=rt2;
return;
}
t[rt1].sum+=t[rt2].sum;
merge(t[rt1].ls,t[rt2].ls);
merge(t[rt1].rs,t[rt2].rs);
}
inline int query(int rt,int l,int r,int k){
if(l==r)return l;
int mid=(l+r)>>1;
if(k<=t[t[rt].rs].sum)return query(t[rt].rs,mid+1,r,k);
else return query(t[rt].ls,l,mid,k-t[t[rt].rs].sum);
}
inline int fd(int x){
if(f[x]==x)return x;
return f[x]=fd(f[x]);
}
int main(){
cin>>n>>m>>q;
for(int i=1;i<=n;++i)f[i]=i;
for(int i=1;i<=n;++i)read(h[i]),hb[i]=h[i];
sort(hb+1,hb+n+1);nn=unique(hb+1,hb+n+1)-(hb+1);
for(int i=1;i<=n;++i)insert(rt[i],1,nn,lower_bound(hb+1,hb+nn+1,h[i])-hb);
for(int i=1;i<=m;++i){
int u,v,w;
read(u);read(v);read(w);
e[i]=edge{u,v,w};
}
sort(e+1,e+m+1,cmp);
for(int i=1;i<=q;++i){
int u,w,k;
read(u);read(w);read(k);
prob[i]=ques{i,u,w,k};
}
sort(prob+1,prob+q+1,cmp2);
int R=0;
for(int i=1;i<=q;++i){
while(e[R+1].w<=prob[i].w&&R<m){
R++;
int u=e[R].u,v=e[R].v;
merge(rt[fd(v)],rt[fd(u)]);
f[fd(u)]=f[fd(v)];
}
int x=prob[i].u,k=prob[i].k;
if(t[rt[fd(x)]].sum<k)ans[prob[i].id]=-1;
else ans[prob[i].id]=hb[query(rt[fd(x)],1,nn,k)];
}
for(int i=1;i<=q;++i)cout<<ans[i]<<"\n";
}