bzoj4771 七彩树
不得不说这是道好题……
先考虑没有深度限制的情况,显然把每种颜色的点做一个树链的并,再求一个子树标记和就行了,这个没什么难度。
然后考虑有了深度限制的情况,我们可以按深度从小到大依次加入所有点,对每个深度分别维护一棵线段树存储每个点的标记和,查询(x,d)的时候就在x的深度+d对应的线段树中查询子树标记和即可。不难发现每个深度的线段树都是可以从上一个快速更新得到的,那么就可以可持久化了,每次把当前深度的点加入并更新一下树链的并,因此还需要用set维护前驱后继。
被set坑了好久,感觉一年半的STL都白学了……
1 /************************************************************** 2 Problem: 4771 3 User: hzoier 4 Language: C++ 5 Result: Accepted 6 Time:2176 ms 7 Memory:118204 kb 8 ****************************************************************/ 9 #include<cstdio> 10 #include<cstring> 11 #include<algorithm> 12 #include<vector> 13 #include<set> 14 using namespace std; 15 const int maxn=100010,maxm=maxn<<6; 16 void clear(int); 17 void bfs(); 18 int LCA(int,int); 19 void build(int,int,int&); 20 void query(int,int,int); 21 int copy(int); 22 int sm[maxm]={0},lc[maxm]={0},rc[maxm]={0},vis[maxm]={0},root[maxn],cnt=0,tim; 23 vector<int>G[maxn]; 24 int f[maxn][20],d[maxn],dfn[maxn],size[maxn],q[maxn]; 25 struct cmp{bool operator()(int x,int y)const{return dfn[x]<dfn[y];}}; 26 set<int,cmp>st[maxn]; 27 int T,n,m,lgn,a[maxn],x,s,t,k,ans; 28 int main(){ 29 scanf("%d",&T); 30 while(T--){ 31 scanf("%d%d",&n,&m); 32 clear(n); 33 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 34 for(int i=2;i<=n;i++){ 35 scanf("%d",&f[i][0]); 36 G[f[i][0]].push_back(i); 37 } 38 bfs(); 39 for(int j=1;j<=lgn;j++)for(int i=1;i<=n;i++)f[i][j]=f[f[i][j-1]][j-1]; 40 for(int i=1;i<=n;i++){ 41 x=q[i]; 42 if(!root[d[x]])root[d[x]]=root[d[x]-1]; 43 tim=d[x]; 44 k=1; 45 t=dfn[x]; 46 build(1,n,root[d[x]]); 47 set<int,cmp>::iterator u=st[a[x]].lower_bound(x),v=st[a[x]].upper_bound(x); 48 if(u==st[a[x]].begin())u=st[a[x]].end(); 49 else if(u!=st[a[x]].end())u--; 50 else if(!st[a[x]].empty()&&dfn[*st[a[x]].rbegin()]<dfn[x])u=st[a[x]].find(*st[a[x]].rbegin()); 51 if(u!=st[a[x]].end()&&v!=st[a[x]].end()){ 52 t=dfn[LCA(*u,*v)]; 53 build(1,n,root[d[x]]); 54 } 55 k=-1; 56 if(u!=st[a[x]].end()){ 57 t=dfn[LCA(*u,x)]; 58 build(1,n,root[d[x]]); 59 } 60 if(v!=st[a[x]].end()){ 61 t=dfn[LCA(x,*v)]; 62 build(1,n,root[d[x]]); 63 } 64 st[a[x]].insert(x); 65 } 66 for(int i=1;i<=n;i++)if(!root[i])root[i]=root[i-1]; 67 while(m--){ 68 scanf("%d%d",&x,&k); 69 x^=ans;k^=ans; 70 s=dfn[x]; 71 t=dfn[x]+size[x]-1; 72 ans=0; 73 query(1,n,root[min(d[x]+k,n)]); 74 printf("%d\n",ans); 75 } 76 } 77 return 0; 78 } 79 void clear(int n){ 80 fill(sm,sm+cnt+1,0); 81 fill(lc,lc+cnt+1,0); 82 fill(rc,rc+cnt+1,0); 83 fill(vis,vis+cnt+1,0); 84 cnt=tim=0; 85 fill(root,root+n+1,0); 86 for(int i=0;i<=n;i++){ 87 G[i].clear(); 88 memset(f[i],0,sizeof(f[i])); 89 st[i].clear(); 90 } 91 fill(d,d+n+1,0); 92 fill(dfn,dfn+n+1,0); 93 fill(size,size+n+1,0); 94 lgn=ans=0; 95 } 96 void bfs(){ 97 int x,head=1,tail=1; 98 q[tail++]=1; 99 while(head!=tail){ 100 x=q[head++]; 101 dfn[x]=size[x]=1; 102 d[x]=d[f[x][0]]+1; 103 while((1<<lgn)<d[x])lgn++; 104 for(int i=0;i<(int)G[x].size();i++)q[tail++]=G[x][i]; 105 } 106 for(int i=n;i>1;i--){ 107 x=q[i]; 108 dfn[x]+=size[f[x][0]]; 109 size[f[x][0]]+=size[x]; 110 } 111 for(int i=2;i<=n;i++)dfn[q[i]]+=dfn[f[q[i]][0]]-1; 112 } 113 int LCA(int x,int y){ 114 if(d[x]!=d[y]){ 115 if(d[x]<d[y])swap(x,y); 116 for(int i=lgn;i>=0;i--)if(d[f[x][i]]>=d[y])x=f[x][i]; 117 } 118 if(x==y)return x; 119 for(int i=lgn;i>=0;i--)if(f[x][i]!=f[y][i]){ 120 x=f[x][i]; 121 y=f[y][i]; 122 } 123 return f[x][0]; 124 } 125 void build(int l,int r,int &rt){ 126 if(vis[rt]<tim)rt=copy(rt); 127 sm[rt]+=k; 128 if(l==r)return; 129 int mid=(l+r)>>1; 130 if(t<=mid)build(l,mid,lc[rt]); 131 else build(mid+1,r,rc[rt]); 132 } 133 void query(int l,int r,int rt){ 134 if(!rt)return; 135 if(s<=l&&t>=r){ 136 ans+=sm[rt]; 137 return; 138 } 139 int mid=(l+r)>>1; 140 if(s<=mid)query(l,mid,lc[rt]); 141 if(t>mid)query(mid+1,r,rc[rt]); 142 } 143 int copy(int rt){ 144 int x=++cnt; 145 sm[x]=sm[rt]; 146 lc[x]=lc[rt]; 147 rc[x]=rc[rt]; 148 vis[x]=tim; 149 return x; 150 }
233333333