bzoj 4771: 七彩树

4771: 七彩树

Time Limit: 5 Sec  Memory Limit: 256 MB
Submit: 2104  Solved: 601
[Submit][Status][Discuss]

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

Sample Output

1
2
3
1
1
2
1
1

HINT

 

思路:本题是dfs序+树链合并+set维护+主席树。

树链的并+STL-set+DFS序+可持久化线段树

如果没有深度限制,那么对于一种颜色,子树内包含该颜色的节点为:所有该颜色节点到根节点路径覆盖的所有节点,即树链的并。

因此对于每一种颜色求树链的并,支持链加操作;查询单个点的时候就是查询单点值。树上差分后转变为单点加、子树求和,使用DFS序转化为区间问题后使用数据结构维护。

那么有深度限制呢?我们按照深度维护可持久化线段树,第 $i$ 个版本我们只考虑深度小于等于 $i$ 的节点的影响。此时需要使用STL-set维护每个颜色的树链的并。

查询时直接查询depth[x]+d版本对应的可持久化线段树中,x节点子树内的权值和即可。

时间复杂度 $O(n\log n)$ 。

 

 

关于树链合并:

做法

按dfn序排好序后,
所有点到根距离-所有相邻两点lca到根距离为树链的并总长

sort(que+1,que+n+1,cmp);
for(i=1;i<=n;i++) res+=dis[que[i]];
for(i=1;i<=n;i++) res-=dis[LCA(que[i],que[i+1])];

简略证明

如图:

dfn序为anc,x,y,z
求x,y,z树链的并:dis[anc]加3次减2次
求x,y,z,anc树链的并:dis[anc]加4次减3次(LCA(anc,x)=anc)

用途

可以树链的并求和
也可以树链的并修改
可以解决子树不同数问题

 

  1 #include<bits/stdc++.h>
  2 using namespace std;  
  3 #define R register int  
  4 #define rep(i,a,b) for(R i=a;i<=b;i++) 
  5 #define Rep(i,a,b) for(R i=a;i>=b;i--)  
  6 #define mid        (l+r>>1) 
  7 #define gc()       getchar()
  8 #define ms(i,a)    memset(a,i,sizeof(a))    
  9 template<class T>void read(T &x){
 10     x=0; char c=0; 
 11     while (!isdigit(c)) c=gc();  
 12     while (isdigit(c)) x=x*10+(c^48),c=gc();  
 13 }
 14 int const N=100000+3;
 15 int n,m,rt[N],d[N],f[N][17],lc[N*40],rc[N*40],s[N*40],cnt,sum,tin[N],tout[N],tot,H[N],c[N],pos[N];   
 16 set<int> se[N];  
 17 set<int> :: iterator it;  
 18 struct Edge{
 19     int to,nt; 
 20 }E[N];  
 21 struct node{
 22     int id,dp;  
 23     bool operator < (const node &rhs) const { return dp<rhs.dp;} 
 24 }a[N];  
 25 void add(int a,int b){
 26     E[++cnt]=(Edge){b,H[a]}; H[a]=cnt;
 27 }
 28 void dfs(int x,int fa){
 29     f[x][0]=fa;  
 30     d[x]=d[f[x][0]]+1; 
 31     tin[x]=++tot;  pos[tot]=x;  
 32     rep(j,1,16) f[x][j]=f[f[x][j-1]][j-1];  
 33     for(R i=H[x]; i; i=E[i].nt){
 34         int v=E[i].to;  
 35         dfs(v,x);  
 36     }
 37     tout[x]=tot;  
 38 }      
 39 void update(int old,int &x,int p,int l,int r,int v){
 40     x=++sum; lc[x]=lc[old]; rc[x]=rc[old]; s[x]=s[old]+v;  
 41     if(l==r) return ;  
 42     if(p<=mid) update(lc[old],lc[x],p,l,mid,v); 
 43     else update(rc[old],rc[x],p,mid+1,r,v); 
 44 }
 45 int lca(int x,int y){ 
 46     if(d[x]<d[y]) swap(x,y);  
 47     Rep(i,16,0) if((1<<i)<=d[x]-d[y]) x=f[x][i];  
 48     if(x==y) return x;  
 49     Rep(i,16,0) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];  
 50     return f[x][0]; 
 51 }
 52 int query(int x,int l,int r,int ll,int rr){
 53     if (!x) return 0; 
 54     if(ll<=l && r<=rr) return s[x];  
 55     int t1=0,t2=0;  
 56     if(ll<=mid) t1=query(lc[x],l,mid,ll,rr); 
 57     if(rr>mid)  t2=query(rc[x],mid+1,r,ll,rr);  
 58     return t1+t2;     
 59 }
 60 
 61 int main(){
 62     int T; read(T); 
 63     while (T--){
 64         read(n);  
 65         read(m);  
 66            cnt=tot=sum=0;  
 67            ms(0,H);ms(0,rt);    
 68            rep(i,1,n) read(c[i]); 
 69            rep(i,2,n) {
 70                int x; read(x);  
 71                add(x,i);  
 72            }
 73            dfs(1,0);   
 74            rep(i,1,n) a[i].id=i,a[i].dp=d[i];  
 75            sort(a+1,a+n+1);     
 76            rep(i,1,n) se[i].clear();   
 77            int p=1;       
 78            rep(i,1,n) {
 79                rt[i]=rt[i-1];   
 80                while (p<=n && a[p].dp<=i) {
 81                    update(rt[i],rt[i],tin[a[p].id],1,n,1);  
 82                    it=se[c[a[p].id]].lower_bound(tin[a[p].id]);  
 83                    int x=0,y=0;  
 84                    if(it!=se[c[a[p].id]].end()) x=pos[*it];  
 85                    if(it!=se[c[a[p].id]].begin())  y=pos[*(--it)];  
 86                    if(x) update(rt[i],rt[i],tin[lca(x,a[p].id)],1,n,-1);  
 87                    if(y) update(rt[i],rt[i],tin[lca(y,a[p].id)],1,n,-1);  
 88                    if(x && y) update(rt[i],rt[i],tin[lca(x,y)],1,n,1); 
 89                    se[c[a[p].id]].insert(tin[a[p].id]);   
 90                    p++; 
 91                } 
 92            }
 93            int last=0;    
 94            while (m--){
 95                int x,y; read(x); read(y);  
 96                x^=last; y=min(n,(y^last)+d[x]);  
 97                printf("%d\n",last=query(rt[y],1,n,tin[x],tout[x]) );  
 98            }
 99        }
100        return 0; 
101 }
102                    
103                             
104            
View Code

 

 
posted @ 2019-03-22 00:24  zjxxcn  阅读(392)  评论(0编辑  收藏  举报