排序以后,做并茶几+主席树合并维护,Orzstdcall,没想到权值线段树的合并竟然是O(nlogn)的...虽然他给我证明了一波,但是还是不是十分理解...听说是Cydiater给他讲的,Orz
#include<bits/stdc++.h> using namespace std; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch<=‘9‘&&ch>=‘0‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } struct one {int x,id,y,v,f;}; one e[2200010]; int f1,f2,n,m,q,cnt=0,root[501000],hash[501000],fa[501000],a[501000],sum[6000000],l[6000000],r[6000000],ans[500100]; bool cmp(one aa,one bb){if(aa.v==bb.v)return aa.f<bb.f;else return aa.v<bb.v;} void add(int &pre,int L,int R,int x) { if(!pre)pre=++cnt;sum[pre]=1; if(L>=R)return; int mid=(L+R)>>1; if(x<=mid){add(l[pre],L,mid,x);} else {add(r[pre],mid+1,R,x);} } int getfather(int pp) { if(pp==fa[pp])return pp; else return fa[pp]=getfather(fa[pp]); } int merge(int aa,int bb) { if(!aa)return bb; if(!bb)return aa; if((!l[aa])&&(!r[aa])) { sum[aa]+=sum[bb]; return aa; } l[aa]=merge(l[aa],l[bb]); r[aa]=merge(r[aa],r[bb]); sum[aa]=sum[l[aa]]+sum[r[aa]]; return aa; } int query(int pre,int L,int R,int x) { if(L>=R)return L; int mid=(L+R)>>1; if(x<=sum[l[pre]])return query(l[pre],L,mid,x); else return query(r[pre],mid+1,R,x-sum[l[pre]]); } int main() { //freopen("xf.in","r",stdin); //freopen("xf.out","w",stdout); scanf("%d%d%d",&n,&m,&q); for(int i=1;i<=n;i++)a[i]=read(),hash[i]=a[i]; sort(hash+1,hash+n+1); for(int i=1;i<=m;i++) { e[i].x=read(); e[i].y=read(); e[i].v=read(); e[i].f=0; } for(int i=m+1;i<=m+q;i++) { e[i].x=read(); e[i].v=read(); e[i].y=read(); e[i].f=1; e[i].id=i-m; } sort(e+1,e+q+m+1,cmp); for(int i=1;i<=n;i++) { int x=lower_bound(hash+1,hash+n+1,a[i])-hash; add(root[i],1,n,x); } for(int i=1;i<=n;i++)fa[i]=i; for(int i=1;i<=m+q;i++) { if(!e[i].f) { f1=getfather(e[i].x); f2=getfather(e[i].y); if(f1==f2)continue; fa[f1]=f2; root[f2]=merge(root[f1],root[f2]); } else { f1=getfather(e[i].x); if(sum[root[f1]]<e[i].y)ans[e[i].id]=-1; else ans[e[i].id]=hash[query(root[f1],1,n,sum[root[f1]]-e[i].y+1)]; } } for(int i=1;i<=q;i++)printf("%d\n",ans[i]); return 0; }