题目描述

有一棵不断加叶子的树,叶子的权值是0,其余节点的权值是其子节点的 mex \texttt{mex} mex

  • mex \texttt{mex} mex定义为最小的没有出现过的自然数。

解题思路

首先离线建树,把树做轻重链剖分。

对于一个节点 u u u,设其轻儿子中最小的没有出现能过的自然数是 A A A,次小的是 B B B,其重儿子权值是 x x x。

  • 若 x = A x=A x=A,则 v ( u ) = B v(u)=B v(u)=B

  • 若 x ≠ A x\neq A x=A,则 v ( u ) = A v(u)=A v(u)=A

我们可以用一个五元组 ( v , A , B , X , Y ) (v,A,B,X,Y) (v,A,B,X,Y)来描述这样的信息:

  • 若 x = v x=v x=v,则返回的是 A A A,权值和会加上 X X X。

  • 若 x ≠ v x\neq v x=v,则返回的是 B B B,权值和会加上 Y Y Y。

观察到这样的信息是可以合并的,因此我们用线段树维护一条重链的信息。

修改和普通动态 d p dp dp的修改是类似的

有一个小细节是一个点的权值是 O ( log ⁡ n ) O(\log n) O(logn)的,因此可以用数组存储每个点轻子树的点权,方便求出 A , B A,B A,B。

复杂度 O ( n l o g 2 n ) O(nlog^2n) O(nlog2n)

#include<bits/stdc++.h>
using namespace std;
const int N = 3e5+7;
typedef long long LL;
struct Info
{int x;int A1,A2;LL S1,S2; Info(){x=A1=A2=S1=S2=-1;}Info(int a,int b,LL c,int d,LL e){x=a;A1=b;S1=c;A2=d;S2=e;}
};
inline void process(int &v,LL &w,Info U)
{if(v==U.x) {v=U.A1;w+=U.S1;}else{v=U.A2;w+=U.S2;}
}
Info Push(Info A,Info B)
{if(A.x==-1)return B;Info C;C.x=A.x;int v;LL w;v=A.A1,w=A.S1;process(v,w,B);C.A1=v;C.S1=w;v=A.A2;w=A.S2;process(v,w,B);C.A2=v;C.S2=w; return C;
}
int n;
struct edge
{int y,next;
}e[2*N];
int link[N],t=0;
void add(int x,int y)
{e[++t].y=y;e[t].next=link[x];link[x]=t;
}
int siz[N],top[N],son[N],dfn[N],timer=0;
int fa[N],st[N],ed[N];
void dfs(int x,int pre)
{siz[x]=1;fa[x]=pre;for(int i=link[x];i;i=e[i].next){int y=e[i].y;if(y==pre)continue;dfs(y,x);siz[x]+=siz[y];if(siz[y]>siz[son[x]])son[x]=y;}
}
void Exdfs(int x,int topth)
{top[x]=topth;dfn[x]=++timer;if(x==topth) st[x]=dfn[x];ed[top[x]]=dfn[x];
//  cout<<x<<' '<<topth<<' '<<st[topth]<<' '<<ed[topth]<<endl;if(!son[x])return;Exdfs(son[x],topth);for(int i=link[x];i;i=e[i].next){int y=e[i].y;if(y==fa[x]||y==son[x])continue;Exdfs(y,y);}
}
Info tr[N*4];
void update(int k,int l,int r,int x,Info U)
{//  cout<<"update:"<<x<<endl;if(l==r){tr[k]=U;
//  cout<<l<<' '<<r<<' '<<tr[k].x<<' '<<tr[k].A1<<' '<<tr[k].A2<<' '<<tr[k].S1<<' '<<tr[k].S2<<endl;return;}int mid=(l+r)>>1;if(x<=mid) update(k<<1,l,mid,x,U);else update(k<<1|1,mid+1,r,x,U);tr[k]=Push(tr[k<<1|1],tr[k<<1]);
//  cout<<l<<' '<<r<<' '<<tr[k].x<<' '<<tr[k].A1<<' '<<tr[k].A2<<' '<<tr[k].S1<<' '<<tr[k].S2<<endl;
}
Info query(int k,int l,int r,int L,int R)
{if(L<=l&&r<=R)return tr[k];int mid=(l+r)>>1;if(R<=mid)return query(k<<1,l,mid,L,R);if(L>mid) return query(k<<1|1,mid+1,r,L,R);return Push(query(k<<1|1,mid+1,r,mid+1,R),query(k<<1,l,mid,L,mid));
}
int w[N];
int B[N][30];
LL sum=0;
inline void guess(int x,int &u,int &v)
{//  cout<<u<<' '<<v<<' '<<B[x][0]<<endl;for(int i=0;i<=29;i++)if(!B[x][i]){if(u==-1) u=i;else if(v==-1) v=i;}
}
void modify(int x)
{int p=top[fa[x]];while(p){Info U=query(1,1,n+1,st[p],ed[p]);sum-=U.S2;p=top[fa[p]];   }//w[x]=0;update(1,1,n+1,dfn[x],Info(0,1,1,0,0));p=top[x];
//  cout<<x<<':'<<dfn[x]<<endl;//cout<<query(1,1,n,st[1],ed[1]).S2<<endl;while(p){//  cout<<query(1,1,n,st[1],ed[1]).S2<<endl;
//  cout<<"modify:"<<p<<' '<<w[p]<<' '<<st[p]<<' '<<ed[p]<<' '<<sum<<endl;Info U=query(1,1,n+1,st[p],ed[p]);sum+=U.S2;if(!fa[p])break;if(w[p]>=0) B[fa[p]][w[p]]--;w[p]=U.A2;if(w[p]>=0) B[fa[p]][w[p]]++;int u=-1,v=-1;guess(fa[p],u,v);
//      cout<<"guess:"<<u<<' '<<v<<endl;update(1,1,n+1,dfn[fa[p]],Info(u,v,v,u,u));p=top[fa[p]];}
//  if(x==3)exit(0);
}
int cr[N];
int main()
{cin>>n;for(int i=1;i<=n;i++){scanf("%d",&cr[i]);add(cr[i],i+1);}for(int i=1;i<=n+1;i++)w[i]=-1;dfs(1,0);Exdfs(1,1);modify(1);for(int i=1;i<=n;i++){modify(i+1);printf("%lld\n",sum);}return 0;
}

CF1740H MEX Tree Manipulation相关推荐

  1. CF1527D MEX Tree(mex树容斥)

    CF1527D MEX Tree(mex&树&容斥) 考虑简单容斥,meximex_imexi​ 等于包含[0,i−1][0,i-1][0,i−1]的所有路径减取包含[0,i][0,i ...

  2. 5.30 Tree Traversal + Tree manipulation

    Binary Tree Preorder Traversal 题目:对一棵二叉树进行前序遍历,并将结果存在一个List 当中 思路:使用递归 细节: 对于递归版本:注意preorderTraversa ...

  3. HDU - 4747 Mex(线段树)

    题意: 计算    其中mex即为博弈中出现的mex(未出现的最小非负整数). 分析: 有两种方法,递推有点懵(以后再来补QAQ),就写了线段树 想法是每次求以i为起点的区间的mex值的和,最后累加即 ...

  4. 常用的Git Tips

    一.Configuration:配置 列举所有的别名与配置 git config --list Git 别名配置 git config --global alias. git config --glo ...

  5. WebKit Layout 数据结构

    一.Render树的构成 在我们编写网页及使用JS的时候,大概都知道DOM树及其主要构成,了解到DOM树的构建其实质是对一个html或xml文件的内容采取树结构的方式来组织及描述,不同的标签及其在文档 ...

  6. Codeforces Round #721 (Div. 2)

    Codeforces Round #721 (Div. 2) 题号 题目 难度 知识点 A And Then There Were K B Palindrome Game (easy version) ...

  7. [CF/AT]各大网站网赛 体验部部长第一季度工作报告

    文章目录 CodeForces #712 (Div. 1)--1503 A. Balance the Bits B. 3-Coloring C. Travelling Salesman Problem ...

  8. 世界级软件开发大师Martin Fowler这三本书经典书你都读过哪一本?

    马丁·福勒(Martin Fowler),世界级软件开发大师,ThoughtWorks首席科学家.他是一位作家.演说者.咨询师和泛软件开发领域的意见领袖.他致力于改善企业级的软件设计,对优秀的设计以及 ...

  9. CodeForces - 817F MEX Queries(线段树lazy序)

    题目链接:点击查看 题目大意:初始时有一个空的集合,需要执行 n 次操作: 1 l r:将区间 [ l , r ] 内未出现的数加入到集合中 2 l r:将区间 [ l , r ] 内出现的数字全部删 ...

最新文章

  1. 框架退出的方法_AOP日志框架实现
  2. 线上使用zabbix报警脚本(含图片)
  3. [note]浏览器兼容性(embed标签、字体兼容相关
  4. Servlet的第一个程序HelloWorld
  5. 微服务扩展新途径:Messaging
  6. 使用Jenkins,GitHub和Docker的最先进的持续集成和部署管道
  7. zooland 新开源的RPC项目,希望大家在开发的微服务的时候多一种选择,让微服务开发简单,并且容易上手。...
  8. TimePickerView(日期选择器)
  9. (四)Linux 安装 jdk
  10. 第三课:java开发hdfs
  11. localhost提示没有入口_管家婆财贸双全连接失败,服务器端没有找到加密狗
  12. cad一键卸载工具叫什么_CAD卸载清理工具
  13. 【AI视野·今日Robot 机器人论文速览 第二十三期】Tue, 28 Sep 2021
  14. 布局java ee企业级开发_布局JavaEE企业级开发:寻觅框架和开发模式的完美整合...
  15. 中国大学mooc慕课python答案_中国大学mooc慕课_Python游戏开发入门_章节测试答案...
  16. 京东云视频云全面支持AVS2标准
  17. Celery---手机短信异步发送
  18. 马保国一年能挣多少钱?
  19. LiveData的简介
  20. Question Retrieval with Distributed Representations and Participant Reputation in Community QA论文笔记

热门文章

  1. Unity中Animation连续被调用时,Animation Event偶尔不触发
  2. 条码打印出现乱码的解决方案
  3. linux中跳板机的部署
  4. 通信原理中星座图详解
  5. Ubuntu 安装出现 error vmlinuz has invalid signature 【或者】 mmx64.efi not found
  6. 计算机网络之域名解析
  7. 微信小程序前端调用python后端的模型
  8. 学校要求软著申请人只能写学校的名字,版权中心新系统里大学生申请软件著作权(软著)如何以学校为单位发表?附:本人软著申请图
  9. spring boot Java 视频转换:avi转mp4
  10. 218 扑克牌(数学期望)