好题,又学两个思路。


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

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

  • 颜色相同的点按 \(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. 渗透测试-Kioptix Level 1靶机getshell及提权教程

    声明! 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及泷羽sec团队无 ...

  2. 张高兴的 Raspberry Pi AI 开发指南:(二)使用 Python 进行目标检测

    目录 Python 环境配置 实现 USB 摄像头的目标检测 参考 在上一篇博客中,探讨了使用 rpicam-apps 通过 JSON 文件配置并运行目标检测示例程序.虽然这种方法可以实现有效的检测, ...

  3. uni-app生命周期小测

    标签: js uni-app 前情 uni-app是我很喜欢的跨平台框架,它能开发小程序,H5,APP(安卓/iOS),对前端开发很友好,自带的IDE让开发体验也很棒,公司项目就是主推uni-app. ...

  4. 题解:P10704 救赎(Redemption)

    数论题,先看数据范围,发现 $n$ 和 $m$ 都非常大,但是 $\sum_{i=1}^{i=n}a_i \le 10^9$. 解以上不等式得不同的 $a_i$ 大约有 $40000$ 个.记有 $c ...

  5. .NET 中的线程安全数据结构

    目录 1. ConcurrentQueue 2. ConcurrentStack 3. ConcurrentBag 4. ConcurrentDictionary<TKey, TValue> ...

  6. SSM或Spring Boor开发中@Repository和@Mapper的区别

    在做一个SpringBoot项目的时候在Dao层使用了@Repository注解然后报了这个错: Description: Field userService in com.example.demo. ...

  7. 《Hough变换及其在信息处理中的应用》电子书下载

    <Hough变换及其在信息处理中的应用>电子书下载:百度云盘,  提取码:9zyi

  8. OpenGL ES 3.x游戏开发(上+下卷)书籍的电子版+源程序

    直接附上电子书以及源代码下载链接:https://pan.baidu.com/s/1G10hw5aIi-Bc2LyktwKrdg

  9. 理解IM消息“可靠性”和“一致性”问题,以及解决方案探讨

    本文作者"商文默",本次有修订和改动. 1.写在前面 即时通讯网整理的大量IM技术文章中(见本文末"参考资料"一节),有关消息可靠性和一致性问题的文章占了很大比 ...

  10. Datawhale AI 夏令营-天池Better Synth多模态大模型数据合成挑战赛-task3持续上分(更新中)

    在大数据.大模型时代,随着大模型发展,互联网数据渐尽且需大量处理标注,为新模型训练高效合成优质数据成为新兴问题."天池 Better Synth - 多模态大模型数据合成挑战赛"应 ...