[BZOJ3133] [Baltic2013]ballmachine(树上倍增+堆)
[BZOJ3133] [Baltic2013]ballmachine(树上倍增+堆)
题面
有一个装球机器,构造可以看作是一棵树。有下面两种操作:
从根放入一个球,只要下方有空位,球会沿着树滚下。如果同时有多个点可以走,那么会选择编号最小的节点所在路径的方向。比如依次在树根4
放2个球,第一个球会落到1
,第二个会落到3
:
从某个位置拿走一个球,那么它上方的球会落下来。比如依次拿走5, 7, 8
三个球:
分析
我们可以预处理出从根节点放第i个球时,球到达的位置x.因此,对于每个节点x,我们记录放第几个球的时候才能落到x,记为seq[x]。
预处理的时候先dfs一遍,求出每个节点子树中的最小节点编号。然后再dfs一遍,按照子树中的最小节点编号从小到大遍历。实现上直接sort一遍邻接表即可。容易发现,seq[x]就是x在树的后序遍历序列中处在第几个(因为球会尽量往最下方走)
void dfs2(int x,int fa){
for(int i=0;i<(int)E[x].size();i++){//E[x]已经排过序
int y=E[x][i];
if(y!=fa){
dfs2(y,x);
}
}
seq[x]=++tim;
hash_seq[seq[x]]=x;
}
然后考虑动态插入和删除。
维护一个最小堆,满足堆顶元素seq最小。插入的时候弹出堆顶,把堆顶对应的节点的状态标记为有球。
删除节点x的时候,x到根节点链上的节点会往下落一层。因此只需要用树上倍增找到x祖先里深度最浅的有球节点,将它的状态标记为无球,然后插入最小堆.
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#include<vector>
#include<algorithm>
#define maxn 100000
#define maxlogn 21
using namespace std;
int n,m;
int root;
vector<int>E[maxn+5];
int log2n;
int min_id[maxn+5];//子树中节点的最小编号
int anc[maxn+5][maxlogn+5];
int deep[maxn+5];
bool cmp(int x,int y){
return min_id[x]<min_id[y];
}
void dfs1(int x,int fa){
min_id[x]=x;
deep[x]=deep[fa]+1;
anc[x][0]=fa;
for(int i=1;i<=log2n;i++) anc[x][i]=anc[anc[x][i-1]][i-1];
for(int i=0;i<(int)E[x].size();i++){
int y=E[x][i];
if(y!=fa){
dfs1(y,x);
min_id[x]=min(min_id[x],min_id[y]);
}
}
}
int tim;
int seq[maxn+5]; //掉球顺序
int hash_seq[maxn+5];//seq=i的节点编号
int is_ball[maxn+5];//是否有球
priority_queue<int,vector<int>,greater<int> >q;//按落球顺序从小到大,存储没有球的节点
void dfs2(int x,int fa){
for(int i=0;i<(int)E[x].size();i++){
int y=E[x][i];
if(y!=fa){
dfs2(y,x);
}
}
seq[x]=++tim;
hash_seq[seq[x]]=x;
}
int insert(int num){
int ans;
for(int i=1;i<=num;i++){
int x=hash_seq[q.top()];
q.pop();
is_ball[x]=1;
if(i==num){
ans=x;
break;
}
}
return ans;
}
int del(int x){
int orig_x=x;
for(int i=log2n;i>=0;i--){
if(is_ball[anc[x][i]]) x=anc[x][i];
}
is_ball[x]=0;
q.push(seq[x]);
return deep[orig_x]-deep[x];
}
int main(){
int f;
int op,num;
scanf("%d %d",&n,&m);
log2n=log2(n)+1;
for(int i=1;i<=n;i++){
scanf("%d",&f);
if(f==0) root=i;
else E[f].push_back(i);
}
dfs1(root,0);
for(int i=1;i<=n;i++) sort(E[i].begin(),E[i].end(),cmp);
dfs2(root,0);
for(int i=1;i<=n;i++) q.push(seq[i]);
for(int i=1;i<=m;i++){
scanf("%d %d",&op,&num);
if(op==1) printf("%d\n",insert(num));
else printf("%d\n",del(num));
}
}
[BZOJ3133] [Baltic2013]ballmachine(树上倍增+堆)的更多相关文章
- BZOJ3133[Baltic2013]ballmachine
题目描述 https://www.lydsy.com/JudgeOnline/problem.php?id=3133 题解 还是分两个操作来说吧. 先看第一个操作,放球,可以发现,对于祖先节点和后代节 ...
- 【BZOJ 3133】 3133: [Baltic2013]ballmachine (线段树+倍增)
3133: [Baltic2013]ballmachine Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 148 Solved: 66 Descri ...
- BZOJ5415[Noi2018]归程——kruskal重构树+倍增+堆优化dijkstra
题目描述 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个 n 个节点.m 条边的无向连通图(节点的编号从 1 至 n).我们依次用 l,a 描述一条边的长度.海 ...
- BZOJ3545&3551[ONTAK2010]Peaks——kruskal重构树+主席树+dfs序+树上倍增
题目描述 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只 ...
- Codevs 2370 小机房的树 LCA 树上倍增
题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天,他们想爬到一个节点上去搞基,但是作为两只虫子, ...
- NOIP2013 货车运输 (最大生成树+树上倍增LCA)
死磕一道题,中间发现倍增还是掌握的不熟 ,而且深刻理解:SB错误毁一生,憋了近2个小时才调对,不过还好一遍AC省了更多的事,不然我一定会疯掉的... 3287 货车运输 2013年NOIP全国联赛提高 ...
- HDU 4822 Tri-war(LCA树上倍增)(2013 Asia Regional Changchun)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4822 Problem Description Three countries, Red, Yellow ...
- [NOIP2013/Codevs3287]货车运输-最小[大]生成树-树上倍增
Problem 树上倍增 题目大意 给出一个图,给出若干个点对u,v,求u,v的一条路径,该路径上最小的边权值最大. Solution 看到这个题第一反应是图论.. 然而,任意路径最小的边权值最大,如 ...
- 树上倍增求LCA及例题
先瞎扯几句 树上倍增的经典应用是求两个节点的LCA 当然它的作用不仅限于求LCA,还可以维护节点的很多信息 求LCA的方法除了倍增之外,还有树链剖分.离线tarjan ,这两种日后再讲(众人:其实是你 ...
随机推荐
- hbase字典顺序表(即ASCII码表顺序)
- The GuidRepresentation for the reader is CSharpLegacy, which requires the binary sub type to be Uuid
使用客户端链接MongoDb报错 The GuidRepresentation for the reader is CSharpLegacy, which requires the binary su ...
- Ubuntu16.04 同时连接无线网络和以太网端口
背景: 激光雷达VLP16通过以太网线连接电脑.在本博客所述的设置之前,一旦连接以太网线,本机(dell笔记本)的无线网络立即断开,即无法同时连接无线网络和以太网端口. 问题查找: 命令行 $ ip ...
- python build-in function
目录(?)[-] absx alliterable anyiterable basestring binx boolx callableobject chri classmethodfunction ...
- 微信浏览器video播放视频踩坑
video属性介绍 iOS的属性 playsinline On iPhone, video playsinline elements will now be allowed to play inlin ...
- ant design Radio.Group defaultValue 默认选中没生效
版本问题 (3.10.7 版本中使用 defaultValue) <div> <Radio.Group defaultValue="a" buttonStyle= ...
- Codechef TRIPS Children Trips (分块、倍增)
题目链接: https://www.codechef.com/problems/TRIPS 感觉CC有点毒瘤啊.. 题解: 首先有一个性质可能是因为太傻所以网上没人解释,然而我看了半天: 就是正序和倒 ...
- 损坏的RAID5
损坏的RAID5 string讀入卡cin 関同步 ios::sync_with_stdio(false) 由塊號映射到具體位置 塊號id對應第col個字符串 字符串開始的位置st #include& ...
- vim编辑器快捷键
光标控制命令 命令 光标移动 h或^h 向左移一个字符 j或^j或^n 向下移一行 k或^p 向上移一行 l或空格 向右移一个字符 G 移到文件的最后一行 nG 移到文件的第n行 w 移到下一个字的开 ...
- 自动轮播切换tab
一个项目中需要用到类似的功能,自己手写一个轮播切换,不足之处见谅.代码如下 <!DOCTYPE html> <html lang="en"> <hea ...