Bzoj4771 七彩树
Submit: 646 Solved: 189
Description
给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点。每个节点都被染上了某一种颜色,其中第i个节
点的颜色为c[i]。如果c[i]=c[j],那么我们认为点i和点j拥有相同的颜色。定义depth[i]为i节点与根节点的距离
,为了方便起见,你可以认为树上相邻的两个点之间的距离为1。站在这棵色彩斑斓的树前面,你将面临m个问题。
每个问题包含两个整数x和d,表示询问x子树里且depth不超过depth[x]+d的所有点中出现了多少种本质不同的颜色
。请写一个程序,快速回答这些询问。
Input
第一行包含一个正整数T(1<=T<=500),表示测试数据的组数。
每组数据中,第一行包含两个正整数n(1<=n<=100000)和m(1<=m<=100000),表示节点数和询问数。
第二行包含n个正整数,其中第i个数为c[i](1<=c[i]<=n),分别表示每个节点的颜色。
第三行包含n-1个正整数,其中第i个数为f[i+1](1<=f[i]<i),表示节点i+1的父亲节点的编号。
接下来m行,每行两个整数x(1<=x<=n)和d(0<=d<n),依次表示每个询问。
输入数据经过了加密,对于每个询问,如果你读入了x和d,那么真实的x和d分别是x xor last和d xor last,
其中last表示这组数据中上一次询问的答案,如果这是当前数据的第一组询问,那么last=0。
输入数据保证n和m的总和不超过500000。
Output
对于每个询问输出一行一个整数,即答案。
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
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
2
3
1
1
2
1
1
HINT
Source
树 dfs序 主席树 脑洞题
Claris神犇的题果然画风清奇
说到子树查询大概就是dfs序了吧
然而这个深度限制怎么搞啊……
如果不考虑深度限制的话,可以在树上做差分,若两个点同色,它们的权值为1,并且它们的LCA的权值-1,这样求子树和就能得到正确信息。
用主席树按深度递增顺序,以dfs序为下标添加值并维护差分,这样rt[dep[x]+k]-rt[dep[x]]的范围就是需要的信息了。
真是神奇
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 #include<set> 9 using namespace std; 10 const int mxn=100010; 11 int read(){ 12 int x=0,f=1;char ch=getchar(); 13 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 15 return x*f; 16 } 17 inline int min(int a,int b){return a<b?a:b;}// 18 struct edge{ 19 int v,nxt; 20 }e[mxn<<1]; 21 int hd[mxn],mct=0; 22 void add_edge(int u,int v){ 23 e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return; 24 } 25 // 26 int fa[mxn][18]; 27 int dfn[mxn],out[mxn],dtime=0; 28 int dep[mxn],id[mxn]; 29 int cmp(int a,int b){ 30 return dep[a]<dep[b]; 31 } 32 void DFS(int u,int ff){ 33 dfn[u]=++dtime; 34 dep[u]=dep[ff]+1; 35 for(int i=1;i<=17;i++)fa[u][i]=fa[fa[u][i-1]][i-1]; 36 for(int i=hd[u],v;i;i=e[i].nxt){ 37 v=e[i].v; 38 if(v==ff)continue; 39 fa[v][0]=u; 40 DFS(v,u); 41 } 42 out[u]=dtime; 43 return; 44 } 45 int LCA(int x,int y){ 46 if(dep[x]<dep[y])swap(x,y); 47 for(int i=17;i>=0;i--) 48 if(dep[fa[x][i]]>=dep[y])x=fa[x][i]; 49 if(x==y)return y; 50 for(int i=17;i>=0;i--) 51 if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i]; 52 return fa[x][0]; 53 } 54 /////LCA 55 struct node{ 56 int l,r; 57 int smm; 58 }t[mxn*80]; 59 int rt[mxn<<2],cnt=0;//树根 60 int TP[mxn],dct=0;//树根head 61 void update(int p,int v,int l,int r,int y,int &rt){ 62 rt=++cnt; 63 t[rt]=t[y]; 64 t[rt].smm+=v;//标记永久化 65 if(l==r){return;} 66 int mid=(l+r)>>1; 67 if(p<=mid)update(p,v,l,mid,t[y].l,t[rt].l); 68 else update(p,v,mid+1,r,t[y].r,t[rt].r); 69 return; 70 } 71 int query(int L,int R,int l,int r,int rt){ 72 if(!rt)return 0; 73 if(L<=l && r<=R){ 74 return t[rt].smm; 75 } 76 int mid=(l+r)>>1; 77 int res=0; 78 if(L<=mid)res+=query(L,R,l,mid,t[rt].l); 79 if(R>mid)res+=query(L,R,mid+1,r,t[rt].r); 80 return res; 81 } 82 /////SGT 83 int n,m; 84 struct pt{ 85 int dfn,v; 86 friend bool operator < (pt a,pt b){return a.dfn<b.dfn;} 87 }; 88 set<pt>st[mxn]; 89 void add(int dep,int x,int y,int v){ 90 int tmp=LCA(x,y); 91 // printf("dep:%d x:%d y:%d LCA:%d v:%d\n",dep,x,y,tmp,v); 92 update(dfn[tmp],v,1,n,rt[dct],rt[dct+1]); 93 TP[dep]=++dct; 94 return; 95 } 96 void insert(int c,int x){ 97 pt tmp=(pt){dfn[x],x}; 98 st[c].insert(tmp); 99 add(dep[x],x,x,1); 100 set<pt>::iterator it,itL,itR; 101 it=st[c].lower_bound(tmp); 102 itL=it;itL--; 103 itR=it;itR++; 104 /* printf("nowc:%d nowx:%d\n",c,x); 105 if(it!=st[c].begin()){ 106 printf("left:%d\n",(*itL).v); 107 } 108 if(itR!=st[c].end()){ 109 printf("right:%d\n",(*itR).v); 110 }*/ 111 112 if(it!=st[c].begin() && itR!=st[c].end()){ 113 add(dep[x],(*itL).v,(*itR).v,1); 114 add(dep[x],(*itL).v,x,-1); 115 add(dep[x],x,(*itR).v,-1); 116 } 117 else if(it!=st[c].begin()){ 118 add(dep[x],(*itL).v,x,-1); 119 } 120 else if(itR!=st[c].end()){ 121 add(dep[x],x,(*itR).v,-1); 122 } 123 return; 124 } 125 /////SET 126 int last=0,ans=0,mxdep=0; 127 int c[mxn]; 128 void solve(){ 129 int x,d; 130 for(int i=1;i<=m;i++){ 131 x=read()^last;d=read()^last; 132 ans=query(dfn[x],out[x],1,n,rt[TP[min(mxdep,dep[x]+d)]]); 133 last=ans; 134 printf("%d\n",ans); 135 } 136 return; 137 } 138 void init(int n){ 139 for(int i=1;i<=cnt;i++) t[i].l=t[i].r=t[i].smm=0; 140 // memset(t,0,sizeof t); 141 memset(hd,0,sizeof hd); 142 memset(rt,0,sizeof rt); 143 memset(TP,0,sizeof TP); 144 for(int i=1;i<=n;i++) 145 st[i].clear(); 146 mct=0;cnt=0; 147 last=ans=0; 148 dct=0;dtime=0; 149 return; 150 } 151 int main(){ 152 int i,j,u,v; 153 int T=read(); 154 while(T--){ 155 n=read();m=read(); 156 init(n); 157 for(i=1;i<=n;i++) 158 c[i]=read(); 159 for(i=2;i<=n;i++){ 160 u=read(); 161 add_edge(u,i); 162 } 163 DFS(1,0); 164 for(i=1;i<=n;i++)id[i]=i; 165 sort(id+1,id+n+1,cmp);//按照深度排序 166 for(i=1;i<=n;i++){ 167 u=id[i];int d=dep[u]; 168 // printf("u:%d d:%d\n",u,d); 169 insert(c[u],u); 170 } 171 mxdep=dep[id[n]]; 172 solve(); 173 } 174 return 0; 175 }
本文为博主原创文章,转载请注明出处。