[bzoj3545]Peaks
离线读入并按照困难度排序,即相当于支持两种操作:连边和查询。对于每一个连通块在根节点建一个权值线段树,连边即合并两颗线段树,而查询就是在一棵线段树中查询(注意:边数和询问为$5*10^{5}$)。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define mid (l+r>>1) 4 #define N 200005 5 struct ji{ 6 int x,y,z,id; 7 }e[N*10]; 8 int V,n,m,q,t,f[N],a[N],b[N],r[N],ans[N*5],sz[N*20],ls[N*20],rs[N*20]; 9 bool cmp(ji x,ji y){ 10 return (x.z<y.z)||(x.z==y.z)&&(x.id<y.id); 11 } 12 void read(int &n){ 13 char c=0; 14 while (!isdigit(c))c=getchar(); 15 while (isdigit(c)){ 16 n=n*10+(c^48); 17 c=getchar(); 18 } 19 } 20 int find(int k){ 21 if (k==f[k])return k; 22 return f[k]=find(f[k]); 23 } 24 void update(int k,int l,int r,int x){ 25 sz[k]=1; 26 if (l==r)return; 27 if (x<=mid)update(ls[k]=++V,l,mid,x); 28 else update(rs[k]=++V,mid+1,r,x); 29 } 30 int merge(int x,int y){ 31 if (x*y==0)return x+y; 32 if (ls[x]+rs[x]==0)sz[x]+=sz[y]; 33 else sz[x]=sz[ls[x]=merge(ls[x],ls[y])]+sz[rs[x]=merge(rs[x],rs[y])]; 34 return x; 35 } 36 int query(int k,int l,int r,int x){ 37 if (l==r)return l; 38 if (x<=sz[ls[k]])return query(ls[k],l,mid,x); 39 else return query(rs[k],mid+1,r,x-sz[ls[k]]); 40 } 41 int main(){ 42 read(n); 43 read(m); 44 read(q); 45 for(int i=1;i<=n;i++){ 46 read(a[i]); 47 b[f[i]=i]=a[i]; 48 } 49 sort(b+1,b+n+1); 50 t=unique(b+1,b+n+1)-b-1; 51 for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+t+1,a[i])-b; 52 for(int i=1;i<=n;i++)update(r[i]=++V,1,t,a[i]); 53 for(int i=1;i<=m+q;i++){ 54 read(e[i].x); 55 read(e[i].y); 56 read(e[i].z); 57 if (i>m){ 58 e[i].id=i-m; 59 swap(e[i].y,e[i].z); 60 } 61 } 62 m+=q; 63 sort(e+1,e+m+1,cmp); 64 for(int i=1;i<=m;i++){ 65 e[i].x=find(e[i].x); 66 if (!e[i].id){ 67 e[i].y=find(e[i].y); 68 if (e[i].x==e[i].y)continue; 69 f[e[i].x]=e[i].y; 70 r[e[i].y]=merge(r[e[i].x],r[e[i].y]); 71 } 72 else 73 if (sz[r[e[i].x]]<e[i].y)ans[e[i].id]=-1; 74 else ans[e[i].id]=b[query(r[e[i].x],1,t,sz[r[e[i].x]]-e[i].y+1)]; 75 } 76 for(int i=1;i<=q;i++)printf("%d\n",ans[i]); 77 return 0; 78 }