Bzoj4771 七彩树

Time Limit: 5 Sec  Memory Limit: 256 MB
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

Sample Output

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 }

 

posted @ 2017-03-29 10:38  SilverNebula  阅读(369)  评论(0编辑  收藏  举报
AmazingCounters.com