「BZOJ1803」Spoj1487 Query on a tree III
题目大意:给一棵n个节点的树,每个点有一个权值$val_i$,m次查询,每次查询x的子树中第k大的节点的编号,权值不重复,且树以1为根。
做法:看起来就是一个查询区间第k大强行上树,于是dfs序做
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 inline ll read() { 5 ll x=0,f=1; char ch=getchar(); 6 for(;ch<'0'||ch>'9';ch=getchar()) 7 if(ch=='-')f=-f; 8 for(;ch>='0'&&ch<='9';ch=getchar()) 9 x=x*10+ch-'0'; 10 return x*f; 11 } 12 inline void chkmin( int &a,int b ) { if(a>b) a=b; } 13 inline void chkmax( int &a,int b ) { if(a<b) a=b; } 14 #define _ read() 15 #define ln endl 16 const int N=1e5+5; 17 vector < int > G[N]; 18 int n,m,a[N],val[N],b[N],tot,id[N]; 19 int T[N],sum[20*N],l[N],r[N],lc[20*N],rc[20*N]; 20 inline void insert( int v,int l,int r,int x,int &y ) { 21 y=++tot; sum[y]=sum[x]+1; 22 if(l==r) return; 23 int mid=(l+r)>>1; 24 lc[y]=lc[x]; rc[y]=rc[x]; 25 if(v<=mid) insert(v,l,mid,lc[x],lc[y]); 26 else insert(v,mid+1,r,rc[x],rc[y]); 27 } 28 inline int query( int k,int l,int r,int x,int y ) { 29 if(k>sum[y]-sum[x]) return 0; 30 if(l==r) return l; 31 int mid=(l+r) >> 1; 32 if(sum[lc[y]]-sum[lc[x]]>=k) return query(k,l,mid,lc[x],lc[y]); 33 else return query(k-(sum[lc[y]]-sum[lc[x]]),mid+1,r,rc[x],rc[y]); 34 } 35 inline void dfs( int x,int fa ) { 36 l[x]=++tot; val[tot]=a[x]; 37 for( int i=0;i<G[x].size();i++ ) { 38 int y=G[x][i]; 39 if(y!=fa) dfs(y,x); 40 } 41 r[x]=tot; 42 } 43 int main() { 44 n=_; 45 for( int i=1;i<=n;i++ ) a[i]=_,b[i]=a[i]; 46 sort(b+1,b+n+1); m=unique(b+1,b+n+1)-b-1; 47 for( int i=1;i<=n;i++ ) a[i]=lower_bound(b+1,b+m+1,a[i])-b; 48 for( int i=1;i<=n;i++ ) b[a[i]]=i; 49 for( int i=1;i<n;i++ ) { 50 int x=_,y=_; 51 G[x].push_back(y); G[y].push_back(x); 52 } dfs(1,0); 53 for( int i=1;i<=n;i++ ) insert(val[i],1,n,T[i-1],T[i]); 54 m=_; 55 while(m--) { 56 int x=_,k=_; 57 printf("%d\n",b[query(k,1,n,T[l[x]-1],T[r[x]])]); 58 } 59 }