链接:https://ac.nowcoder.com/acm/problem/16547
来源:牛客网
时间限制:C/C++ 4秒,其他语言8秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
给定一棵树,1为根,树上每个点有一个颜色
给q次询问,每次询问以x为根的子树中深度在[dep[x],dep[x]+y]之间的点的颜色集合(相同颜色只算一遍)中编号第k小的颜色是什么,无解输出-1
输入描述:
第一行,两个数n q 第二行n-1个数,表示2到n的父亲 第三行n个数,表示n个点的颜色 接下来q行 每行三个数x y k,表示一次询问
输出描述:
输出q行,对于每个询问,输出一个数表示答案
示例1
输入
复制
5 3 1 1 2 2 1 2 1 3 2 1 1 2 1 2 3 2 1 1
输出
复制
2 3 2
备注:
n<=105,q<=105
颜色在[1,n]之间
ps:整体二分法,将颜色分成块,用树状数组维护每一块的数目,遍历块数就可以得出答案,同时对于当前节点先加入非最大子树的点(这样就可以先算出非最大子树的答案),然后再将最大子树加入,因为加入非最大子树的点在查完后都要清掉,留下最大子树就可以少删很多点,看代码理解吧
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int>P;
const int maxn = 1e5+9;
const int INF = 0x3f3f3f3f;
struct rt{
int v,next;
}edge[maxn];
struct node{
int y,k,id;
};
int n,q;
int tot,S;
int head[maxn],col[maxn],in[maxn],mm[maxn];
int bit[500][maxn];
int dep[maxn],siz[maxn],son[maxn];
void add_edge(int u,int v){
edge[tot].v=v;
edge[tot].next=head[u];
head[u]=tot++;
}
vector<node>Q[maxn];
int ans[maxn];
void dfn(int u,int fa){
dep[u]=dep[fa]+1;
siz[u]=1;
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].v;
dfn(v,u);
siz[u]+=siz[v];
if(siz[son[u]]<siz[v])son[u]=v;
}
}
void update(int *p,int l,int x){
while(l<=n){
p[l]+=x;
l+=(l&-l);
}
}
int query(int *p,int x,int y){
int sum=0;
x--;
while(x>=1){
sum-=p[x];
x-=(x&-x);
}
while(y>=1){
sum+=p[y];
y-=(y&-y);
}
return sum;
}
void upd(int u){
if(mm[col[u]]<=dep[u])return;
if(mm[col[u]]!=INF)update(bit[in[col[u]]],mm[col[u]],-1);
mm[col[u]]=dep[u];
update(bit[in[col[u]]],dep[u],1);
}
void get(int u){
for(int i=head[u];~i;i=edge[i].next)get(edge[i].v);upd(u);
}
void del(int u){
for(int i=head[u];~i;i=edge[i].next)del(edge[i].v);
if(mm[col[u]]==INF)return;
if(mm[col[u]]!=INF)update(bit[in[col[u]]],mm[col[u]],-1);
mm[col[u]]=INF;
}
void dfs(int u,int fp=1){
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].v;
if(v!=son[u])dfs(v,0);
}
if(son[u])dfs(son[u]);
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].v;
if(v!=son[u])get(v);
}
upd(u);
for(int i=0;i<Q[u].size();i++){
int x=dep[u],y=dep[u]+Q[u][i].y,k=Q[u][i].k;
y=min(y,n);
ans[Q[u][i].id]=-1;
for(int j=0;j<S;j++){
int sum=query(bit[j],x,y);
if(k>sum){k-=sum;continue;}
for(int l=j*S;;l++){
int w=(mm[l]>=x&&mm[l]<=y);
if(w<k){k-=w;continue;}
ans[Q[u][i].id]=l;break;
}
break;
}
}
if(fp)return; del(u);
}
int main(){
memset(head,-1,sizeof(head));
memset(mm,0x3f,sizeof(mm));
scanf("%d%d",&n,&q);
int u;
for(int i=2;i<=n;i++){
scanf("%d",&u);
add_edge(u,i);
}
S=(int)sqrt(n)+1;
for(int i=1;i<=n;i++){
scanf("%d",&col[i]);
in[i]=i/S;
}
dep[1]=1;
dfn(1,0);
int x,y,k;
for(int i=0;i<q;i++){
scanf("%d%d%d",&x,&y,&k);
Q[x].push_back(node{y,k,i});
}
dfs(1);
for(int i=0;i<q;i++){
printf("%d\n",ans[i]);
}
return 0;
}