好题,又学两个思路。


先把问题变简单一点,去掉深度限制,那么有两种做法:

  • 经典的前驱后继转化到二维数点。

  • 颜色相同的点按 \(dfs\) 序排序,每个点 \(+1\),相邻两点 \(lca-1\)。转化为区间求和。

第二种相对实现简单。

假如加上深度,我们可以离线问题,按深度顺序加点。

要在线的话,只需要将线段树改为主席树即可。

时间复杂度 \(O(\sum (n+m)\log n)\)。

除了刚才说到的主席树外,本题在实现过程中还需要用到单调栈(记录自己插入时已经插入且颜色相同的前驱后继)。

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5,M=3e7+5;
int n,tot,low[N],id;
int m,q,dfn[N],a[N];
int tp,sk[N],ij,rt[N];
int t,dep[N],st[N][20];
int fs[N],pr[N],nx[N];
int ls[M],rs[M],sm[M];
vector<int>g[N],cl[N];
int cmp(int x,int y){
return dfn[x]<dfn[y];
}int cmd(int x,int y){
return dep[x]<dep[y];
}int cmb(int x,int y){
return dep[x]!=dep[y]?cmd(x,y):x<y;
}void dfs(int x,int fa){
fs[x]=++ij,dfn[x]=++id;
dep[st[ij][0]=x]=dep[fa]+1;
for(auto y:g[x])
dfs(y,x),st[++ij][0]=x;
low[x]=id;
}int minn(int x,int y){
return dep[x]>dep[y]?y:x;
}void ST(){
for(int i=0;i<19;i++)
for(int j=1;j<=ij-(1<<(i+1))+1;j++)
st[j][i+1]=minn(st[j][i],st[j+(1<<i)][i]);
}int rmq(int l,int r){
int k=log2(r-l+1),x=r-(1<<k)+1;
return minn(st[l][k],st[x][k]);
}int lca(int x,int y){
if(fs[x]>fs[y]) swap(x,y);
return rmq(fs[x],fs[y]);
}void add(int &x,int y,int l,int r,int k,int v){
sm[x=++tot]=sm[y]+v;
if(l==r) return;int mid=(l+r)/2;
if(k<=mid) add(ls[x],ls[y],l,mid,k,v),rs[x]=rs[y];
else add(rs[x],rs[y],mid+1,r,k,v),ls[x]=ls[y];
}int sum(int x,int y,int l,int r,int L,int R){
if(L>R) return 0;
if(L<=l&&r<=R) return sm[x]-sm[y];
int mid=(l+r)/2,re=0;
if(L<=mid) re=sum(ls[x],ls[y],l,mid,L,R);
if(R>mid) re+=sum(rs[x],rs[y],mid+1,r,L,R);
return re;
}void solve(){
for(int i=1;i<=n;i++)
pr[i]=nx[i]=0,g[i].clear(),cl[i].clear();
cin>>n>>q,tot=id=ij=0;int la=0;
for(int i=1,x;i<=n;i++)
cin>>x,a[i]=i,cl[x].push_back(i);
for(int i=2,x;i<=n;i++)
cin>>x,g[x].push_back(i);
dfs(1,0),ST();
sort(a+1,a+n+1,cmd),m=dep[a[n]];
for(int i=1,k;i<=n;i++){
k=cl[i].size(),sort(cl[i].begin(),cl[i].end(),cmp);
for(int j=0;j<k;j++){
while(tp&&cmb(cl[i][j],cl[i][sk[tp]])) tp--;
if(tp) pr[cl[i][j]]=cl[i][sk[tp]];sk[++tp]=j;
}while(tp) sk[tp--]=0;
for(int j=k-1;~j;j--){
while(tp&&cmb(cl[i][j],cl[i][sk[tp]])) tp--;
if(tp) nx[cl[i][j]]=cl[i][sk[tp]];sk[++tp]=j;
}while(tp) sk[tp--]=0;
}for(int i=1;i<=n;i++){
int nw=dep[a[i]];rt[nw]=rt[dep[a[i-1]]];
add(rt[nw],rt[nw],1,n,dfn[a[i]],1);
if(nx[a[i]]) add(rt[nw],rt[nw],1,n,dfn[lca(a[i],nx[a[i]])],-1);
if(pr[a[i]]) add(rt[nw],rt[nw],1,n,dfn[lca(a[i],pr[a[i]])],-1);
if(nx[a[i]]&&pr[a[i]])
add(rt[nw],rt[nw],1,n,dfn[lca(pr[a[i]],nx[a[i]])],1);
}while(q--){
int x,d;cin>>x>>d,x^=la,d^=la;
la=sum(rt[min(dep[x]+d,m)],rt[dep[x]-1],1,n,dfn[x],low[x]);
cout<<la<<"\n";
}
}int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>t;
while(t--) solve();
return 0;
}

[BZOJ4771] 七彩树 题解的更多相关文章

  1. [BZOJ4771]七彩树(主席树)

    https://blog.csdn.net/KsCla/article/details/78249148 用类似经典的链上区间颜色计数问题的做法,这个题可以看成是询问DFS在[L[x],R[x]]中, ...

  2. BZOJ4771 七彩树(dfs序+树上差分+主席树)

    考虑没有深度限制怎么做.显然的做法是直接转成dfs序上主席树,但如果拓展到二维变成矩形数颜色数肯定没法做到一个log. 另一种做法是利用树上差分.对于同种颜色的点,在每个点处+1,dfs序相邻点的lc ...

  3. bzoj4771 七彩树 dfs序+主席树+树链的并

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4771 题解 一道不错的树链并的基础练习题. 如果不是树,而是一个数组的话,对于给定区间内的不同 ...

  4. [bzoj4771] 七彩树

    题意 给定一棵n个点,每个点带颜色的有根树.点的编号和颜色编号都在1到n,根的编号为1.m次询问,求x子树中与x距离边数不超过k的点中,颜色的种类数目.每个测试点有多组数据. 分析 不妨设1的父亲为0 ...

  5. BZOJ4771七彩树——可持久化线段树+set+树链的并+LCA

    给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节 点的颜色为c[i].如果c[i]=c[j],那么我们认为点i和点j拥有相同的颜色.定义dept ...

  6. 【BZOJ4771】七彩树(主席树)

    [BZOJ4771]七彩树(主席树) 题面 BZOJ 题解 如果没有深度限制,每次只询问子树内的颜色个数,除了树套树\(dfs\)序加前驱或者后继强行二维数点之外,还有这样一种做法: 把所有相同颜色的 ...

  7. 【BZOJ4771】七彩树 主席树+树链的并

    [BZOJ4771]七彩树 Description 给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节点的颜色为c[i].如果c[i]=c[j], ...

  8. Vijos1448校门外的树 题解

    Vijos1448校门外的树 题解 描述: 校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的…… 如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现 ...

  9. [BZOJ 4771]七彩树(可持久化线段树+树上差分)

    [BZOJ 4771]七彩树(可持久化线段树+树上差分) 题面 给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节点的颜色为c[i].如果c[i] ...

  10. 【bzoj4771】七彩树 树链的并+STL-set+DFS序+可持久化线段树

    题目描述 给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节点的颜色为c[i].如果c[i]=c[j],那么我们认为点i和点j拥有相同的颜色.定义 ...

随机推荐

  1. 零基础学习人工智能—Python—Pytorch学习(十三)

    前言 最近学习了一新概念,叫科学发现和科技发明,科学发现是高于科技发明的,而这个说法我觉得还是挺有道理的,我们总说中国的科技不如欧美,但我们实际感觉上,不论建筑,硬件还是软件,理论,我们都已经高于欧美 ...

  2. Shiro简单入门+个人理解

    身为一个刚刚进入开发行业的学生,进入公司就开始了Shiro框架的应用,特此在这里写下收获. Shiro是apache旗下一个开源安全框架,它将软件系统的安全认证相关的功能抽取出来,实现用户身份认证,权 ...

  3. nanoFramework

    nanoFramework 01: Getting started with nanoFramework! 08: .NET nanoFramework GPIO, I2C, SPI and othe ...

  4. 中电金信:从“互联网+”到“人工智能+”,TA也藏不住了!

    ​ 两会期间,人工智能频上头条 其中"人工智能+"首次进入2024政府工作报告 为人工智能产业的发展注入一剂强心针   从"互联网+"到"人工智能+& ...

  5. .NET 9 New features-JSON序列化

    .NET 9已经发布有一段时间了,近期整理一下.NET 9的新特性,今天重点分享.NET 9 JSON序列化方面的改进. 先引用官方的说明: 在 System.Text.Json 中,.NET 9 提 ...

  6. Java JUC&多线程 基础完整版

    Java JUC&多线程 基础完整版 目录 Java JUC&多线程 基础完整版 1. 多线程的第一种启动方式之继承Thread类 2.多线程的第二种启动方式之实现Runnable接口 ...

  7. Qt/C++音视频开发69-保存监控pcm音频数据到mp4文件/监控录像/录像存储和回放/264/265/aac/pcm等

    一.前言 用ffmpeg做音视频保存到mp4文件,都会遇到一个问题,尤其是在视频监控行业,就是监控摄像头设置的音频是PCM/G711A/G711U,解码后对应的格式是pcm_s16be/pcm_ala ...

  8. Solution Set - “谁将重力悬空,坠入一场蔚蓝的梦”

    目录 0.「NOI Simu.」皮配 1.「BZOJ #4671」异或图 2.「CF 1158F」Density of subarrays 3.「CF 794G」Replace All 4.「UR # ...

  9. CDS标准视图:催款冻结描述 I_DunningBlockingReasonText

    视图名称:催款冻结描述 I_DunningBlockingReasonText 视图类型:基础视图 视图代码: 点击查看代码 @EndUserText.label: 'Dunning Blocking ...

  10. 国家和地区代码列表,ISO 3166-1:2006

    本文根据ISO 3166-1:2006(International Standard Norme Internationale) 英文版(含2007年补充说明)整理.与ISO 3166-1:1997相 ...