CF1740H MEX Tree Manipulation
题目描述
有一棵不断加叶子的树,叶子的权值是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相关推荐
- CF1527D MEX Tree(mex树容斥)
CF1527D MEX Tree(mex&树&容斥) 考虑简单容斥,meximex_imexi 等于包含[0,i−1][0,i-1][0,i−1]的所有路径减取包含[0,i][0,i ...
- 5.30 Tree Traversal + Tree manipulation
Binary Tree Preorder Traversal 题目:对一棵二叉树进行前序遍历,并将结果存在一个List 当中 思路:使用递归 细节: 对于递归版本:注意preorderTraversa ...
- HDU - 4747 Mex(线段树)
题意: 计算 其中mex即为博弈中出现的mex(未出现的最小非负整数). 分析: 有两种方法,递推有点懵(以后再来补QAQ),就写了线段树 想法是每次求以i为起点的区间的mex值的和,最后累加即 ...
- 常用的Git Tips
一.Configuration:配置 列举所有的别名与配置 git config --list Git 别名配置 git config --global alias. git config --glo ...
- WebKit Layout 数据结构
一.Render树的构成 在我们编写网页及使用JS的时候,大概都知道DOM树及其主要构成,了解到DOM树的构建其实质是对一个html或xml文件的内容采取树结构的方式来组织及描述,不同的标签及其在文档 ...
- Codeforces Round #721 (Div. 2)
Codeforces Round #721 (Div. 2) 题号 题目 难度 知识点 A And Then There Were K B Palindrome Game (easy version) ...
- [CF/AT]各大网站网赛 体验部部长第一季度工作报告
文章目录 CodeForces #712 (Div. 1)--1503 A. Balance the Bits B. 3-Coloring C. Travelling Salesman Problem ...
- 世界级软件开发大师Martin Fowler这三本书经典书你都读过哪一本?
马丁·福勒(Martin Fowler),世界级软件开发大师,ThoughtWorks首席科学家.他是一位作家.演说者.咨询师和泛软件开发领域的意见领袖.他致力于改善企业级的软件设计,对优秀的设计以及 ...
- CodeForces - 817F MEX Queries(线段树lazy序)
题目链接:点击查看 题目大意:初始时有一个空的集合,需要执行 n 次操作: 1 l r:将区间 [ l , r ] 内未出现的数加入到集合中 2 l r:将区间 [ l , r ] 内出现的数字全部删 ...
最新文章
- 框架退出的方法_AOP日志框架实现
- 线上使用zabbix报警脚本(含图片)
- [note]浏览器兼容性(embed标签、字体兼容相关
- Servlet的第一个程序HelloWorld
- 微服务扩展新途径:Messaging
- 使用Jenkins,GitHub和Docker的最先进的持续集成和部署管道
- zooland 新开源的RPC项目,希望大家在开发的微服务的时候多一种选择,让微服务开发简单,并且容易上手。...
- TimePickerView(日期选择器)
- (四)Linux 安装 jdk
- 第三课:java开发hdfs
- localhost提示没有入口_管家婆财贸双全连接失败,服务器端没有找到加密狗
- cad一键卸载工具叫什么_CAD卸载清理工具
- 【AI视野·今日Robot 机器人论文速览 第二十三期】Tue, 28 Sep 2021
- 布局java ee企业级开发_布局JavaEE企业级开发:寻觅框架和开发模式的完美整合...
- 中国大学mooc慕课python答案_中国大学mooc慕课_Python游戏开发入门_章节测试答案...
- 京东云视频云全面支持AVS2标准
- Celery---手机短信异步发送
- 马保国一年能挣多少钱?
- LiveData的简介
- Question Retrieval with Distributed Representations and Participant Reputation in Community QA论文笔记