题意:
一棵树,每次查询某个子树的第k大
思路:
询问子树的问题,因为子树的dfs序是连续的一个区间,所以我们将这棵树dfs地建立主席树,查询子树就是查询子树对应的区间,这样就把树变成数列了
错误及反思:
其实很简单,但是spoj卡常啊,在优化了常数,vector变成链式前向星,用了快读,换头文件以后终于ac了
代码:
#include<map>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
#define lson l,m
#define rson m+1,r
const int N = 101000;
int sum[N*20],ls[N*20],rs[N*20],val[N],root[N],fa[N],to[N],rnk[N],id[N],first[N];
int n,q,tot=1,cnt=0,tid=0;
vector<int> v;
map<int,int> mp;
struct EDGE{
int to,next;
}e[N*2];
inline int read() {
char ch = getchar(); int x = 0, f = 1;
while(ch < '0' || ch > '9') {
if(ch == '-') f = -1;
ch = getchar();
} while('0' <= ch && ch <= '9') {
x = x * 10 + ch - '0';
ch = getchar();
} return x * f;
}
void addedge(int x,int y){
e[tid].to=y;
e[tid].next=first[x];
first[x]=tid++;
e[tid].to=x;
e[tid].next=first[y];
first[y]=tid++;
}
int getid(int x){return lower_bound(v.begin(),v.end(),x)-v.begin()+1;}
int build(int l,int r){
int rt=++cnt;
ls[rt]=rt; rs[rt]=rt; sum[rt]=0;
if(l==r) return rt;
int m=l+r>>1;
ls[rt]=build(lson);
rs[rt]=build(rson);
return rt;
}
int update(int pre,int pos,int l,int r){
int rt=++cnt;
ls[rt]=ls[pre]; rs[rt]=rs[pre]; sum[rt]=sum[pre]+1;
if(l==r) return rt;
int m=l+r>>1;
if(m>=pos) ls[rt]=update(ls[pre],pos,lson);
else rs[rt]=update(rs[pre],pos,rson);
return rt;
}
void dfs(int now,int Fa){
root[tot]=update(root[tot-1],getid(val[now]),1,v.size());
id[now]=tot;
fa[now]=Fa; tot++;
for(int i=first[now];i!=-1;i=e[i].next)
if(e[i].to!=Fa)
dfs(e[i].to,now);
to[now]=tot-1;
}
int query(int r1,int r2,int k,int l,int r){
if(l==r) return rnk[l-1];
int m=l+r>>1,num=sum[ls[r2]]-sum[ls[r1]];
if(num>=k) return query(ls[r1],ls[r2],k,lson);
return query(rs[r1],rs[r2],k-num,rson);
}
int main(){
memset(first,-1,sizeof(first));
n=read();
for(int i=1;i<=n;i++){ val[i]=read(); mp[val[i]]=i; v.push_back(val[i]);}
sort(v.begin(),v.end());
for(int i=0;i<v.size();i++){
rnk[i]=mp[v[i]];
}
for(int i=1,u,v;i<n;i++){
u=read(); v=read();
addedge(u,v);
}
root[0]=build(1,v.size());
dfs(1,0);
scanf("%d",&q);
while(q--){
int x,k;scanf("%d%d",&x,&k);
printf("%d\n",query(root[id[x]-1],root[to[x]],k,1,v.size()));
}
}