Claris Loves Painting
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 256000/256000 K (Java/Others)
Total Submission(s): 524 Accepted Submission(s): 148
Problem Description
Claris loves painting very much, so he painted a tree with beautiful colors.
The tree is a rooted tree with n nodes which are conveniently labeled by 1,2,...,n. Its root is the 1-st node, and the i-th node is painted with color ci. If ci=cj, then we think these two nodes have the same color.
We define depthi as the distance between the i-th node and the root, and simply, the distance between two adjacent nodes is always 1.
Standing in front of this beautiful tree, Claris comes up with m questions.
In each question, there are two integers x and d, which means that Claris wants to know the number of different kinds of colors occur in S, where S={v|v in x′s subtree and depthv≤depthx+d}.
Input
The first line of the input contains an integer T(1≤T≤500), denoting the number of test cases.
In every test case, there are two integers n(1≤n≤100000) and m(1≤m≤100000) in the first line, denoting the number of nodes and queries.
The second line contains n integers, the i-th integer ci(1≤ci≤n) denotes the color of the i-th node.
The third line contains n−1 integers, the i-th integer fi+1(1≤fi<i) denotes the father of the i+1-th node.
In the following m lines, each line contains two integers x(1≤x≤n) and d(0≤d<n), denoting each query.
The input has been encoded, if you read x and d, the real x and d are x⊕last and d⊕last, where last is the answer of the previous query and ⊕ means bitwise exclusive-or.
Notice :
If it is the first query in this test case, then last=0.
It is guaranteed that ∑n≤500000 and ∑m≤500000.
Output
For each query output a single integer in a line, denoting the answer.
Sample Input
1 5 8 1 3 3 2 2 1 1 3 3 1 0 0 0 3 0 1 3 2 1 2 0 6 2 4 1
Sample Output
1 2 3 1 1 2 1 1
Source
Recommend
liuyiding
题意:一棵有根树,树上每一个点有可能相同的颜色,现在要求回答若干个询问,求在u的子树内与u相距不超过d的点有多少种颜色。强制在线。
解题思路:线段树合并,这里用来锻炼下线段树合并的动态开点写法,同时熟悉下线段树的结构体写法。
具体思路参考博客:http://sycstudio.com/archives/513
#include<iostream>
#include<string.h>
#include<queue>
#include<bitset>
#include<vector>
using namespace std;
typedef long long ll;
const int MAXN=100105;
int N,M;
vector<int> G[MAXN];
int C[MAXN];
int dep[MAXN];
//学习一下结构体写法……
struct Node{
int ls,rs,val;
}node[MAXN*110];
int tot;
int root1[MAXN];//每个深度的颜色数
int root2[MAXN];//每个颜色最浅的那个位置
int update(int P,int C,int l,int r,int rt){
int nrt=++tot;
node[nrt].val=node[rt].val+C;//由于第二棵线段树只关心叶子结点信息,所以用一个update实现就好了
if(l==r)
return nrt;
int m=(l+r)/2;
if(P<=m){
node[nrt].ls=update(P,C,l,m,node[rt].ls);
node[nrt].rs=node[rt].rs;
}
else{
node[nrt].rs=update(P,C,m+1,r,node[rt].rs);
node[nrt].ls=node[rt].ls;
}
return nrt;
}
int merge1(int r1,int r2,int l,int r){
if(r1==0||r2==0)
return r1+r2;
int nrt=++tot;//记得新建节点
node[nrt].val=node[r1].val+node[r2].val;//直接合并
if(l==r)
return nrt;
int m=(l+r)/2;
node[nrt].ls=merge1(node[r1].ls,node[r2].ls,l,m);
node[nrt].rs=merge1(node[r1].rs,node[r2].rs,m+1,r);
return nrt;
}
int merge2(int r1,int r2,int l,int r,int u){
if(r1==0||r2==0)
return r1+r2;
int nrt=++tot;
if(l==r){
//根据小的那个来更新
if(node[r1].val>node[r2].val){
node[nrt].val=node[r2].val;
root1[u]=update(node[r1].val,-1,1,N,root1[u]);
}
else{
node[nrt].val=node[r1].val;
root1[u]=update(node[r2].val,-1,1,N,root1[u]);
}
return nrt;
}
int m=(l+r)/2;
node[nrt].ls=merge2(node[r1].ls,node[r2].ls,l,m,u);
node[nrt].rs=merge2(node[r1].rs,node[r2].rs,m+1,r,u);
return nrt;
}
int query(int P,int l,int r,int rt){
if(!rt)
return 0;
if(r<=P)
return node[rt].val;
int m=(l+r)/2;
int ans=query(P,l,m,node[rt].ls);
if(P>=m+1)
ans+=query(P,m+1,r,node[rt].rs);
return ans;
}
void dfs(int x){
root1[x]=update(dep[x],1,1,N,0);
root2[x]=update(C[x],dep[x],1,N,0);
for(int i=0;i<G[x].size();i++){
int v=G[x][i];
dep[v]=dep[x]+1;
dfs(v);
root1[x]=merge1(root1[x],root1[v],1,N);
root2[x]=merge2(root2[x],root2[v],1,N,x);
}
}
int main(){
int T;
scanf("%d",&T);
for(int qqq=1;qqq<=T;qqq++){
scanf("%d%d",&N,&M);
for(int i=1;i<=N;i++){
scanf("%d",&C[i]);
G[i].clear();
}
int x;
for(int i=2;i<=N;i++){
scanf("%d",&x);
G[x].push_back(i);
}
tot=0;
node[0].ls=node[0].rs=node[0].val=0;
dep[1]=1;
dfs(1);
int lastans=0;
for(int i=1;i<=M;i++){
int u,d;
scanf("%d%d",&u,&d);
u^=lastans;
d^=lastans;
printf("%d\n",lastans=query(min(dep[u]+d,N),1,N,root1[u]));
}
}
return 0;
}