题目描述

有一个装球机器,构造可以看作是一棵树。有下面两种操作:

  • 从根放入一个球,只要下方有空位,球会沿着树滚下。如果同时有多个点可以走,那么会选择编号最小的节点所在路径的方向。比如依次在树根4放2个球,第一个球会落到1,第二个会落到3
  • 从某个位置拿走一个球,那么它上方的球会落下来。比如依次拿走5, 7, 8三个球:

输入

第一行:球的个数N,操作个数Q (N, Q <= 100 000)下面N行:第i个节点的父亲。如果是根,则为0 接下来Q行:op num

  1. op == 1:在根放入num个球
  2. op == 2:拿走在位置num的球

输出

保证输入合法

  1. op == 1:输出最后一个球落到了哪里
  2. op == 2:输出拿走那个球后有多少个球会掉下来

样例输入

8 4
0
1
2
2
3
3
4
6
1 8
2 5
2 7
2 8

样例输出

1
3
2
2

这道题有两个操作,删球和加球,对于1操作,可以发现两个特性:1、对于一个节点,它下面的节点没填满,这个节点不会被填上。2、对于一个节点,它子树最小编号的子树没填满,其他子树不会被填球。那么就可以以子树最小编号的大小为顺序维护一个dfs序,在dfs序上,如果前面的位置没填满,后面的位置不会被填。如果因为删除而导致一段被填满的区间中有节点空缺,可以用小根堆(也可以优先队列)来每次取优先度最大的插入。删除操作就是删除一个节点上的球,然后这的节点到根节点链上所有球都向下落一层,也可以看作是把链上最上面有球的节点的球删掉,那么只要找到距离根最近的有球节点就行,但如果一层一层往上爬显然时间复杂度太高,所以需要倍增往上跳。
最后附上代码.
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
priority_queue< int,vector<int>,greater<int> >q;
vector<int>v[200010];
int n,Q;
int f[20][200010];//倍增祖先
int m[200010];//子树最小的编号
int s[200010];//优先度
int r[200010];//优先度对应节点
int cnt;
int root;
int x,y;
int opt;
int d[200010];//深度
int vis[200010];//是否被填标记
bool cmp(int x,int y)
{
return m[x]<m[y];
}
void dfs(int x)//按子树最小编号大小排序并处理深度
{
m[x]=x;
for(int i=0;i<v[x].size();i++)
{
f[0][v[x][i]]=x;
d[v[x][i]]=d[x]+1;
dfs(v[x][i]);
m[x]=min(m[x],m[v[x][i]]);
}
sort(&v[x][0],&v[x][v[x].size()],cmp);
}
void getsign(int x)//处理优先度
{
for(int i=0;i<v[x].size();i++)
{
getsign(v[x][i]);
}
s[x]=++cnt;
r[cnt]=x;
}
int main()
{
scanf("%d%d",&n,&Q);
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
if(x==0)
{
root=i;
}
else
{
v[x].push_back(i);
}
}
for(int i=1;i<=n;i++)
{
q.push(i);
}
d[root]=1;
dfs(root);
getsign(root);
for(int i=1;i<=20;i++)
{
for(int j=1;j<=n;j++)
{
f[i][j]=f[i-1][f[i-1][j]];
}
}
while(Q--)
{
scanf("%d%d",&opt,&x);
if(opt==1)
{
while(x--)
{
y=r[q.top()];
q.pop();
vis[y]=1;
}
printf("%d\n",y);
}
else
{
int fa=x;
for(int i=20;i>=0;i--)
{
if(vis[f[i][x]]==1)
{
x=f[i][x];
}
}
vis[x]=0;
printf("%d\n",d[fa]-d[x]);
q.push(s[x]);
}
}
}

BZOJ3133[ballmachine]——倍增+优先队列的更多相关文章

  1. CF786C-Till I Collapse【树状数组倍增,优先队列】

    正题 题目链接:https://www.luogu.com.cn/problem/CF786C 题目大意 给出一个长度为\(n\)的序列. 对于每个\(k\in[1,n]\)求将\(n\)分成最少的段 ...

  2. [BZOJ3133] [Baltic2013]ballmachine(树上倍增+堆)

    [BZOJ3133] [Baltic2013]ballmachine(树上倍增+堆) 题面 有一个装球机器,构造可以看作是一棵树.有下面两种操作: 从根放入一个球,只要下方有空位,球会沿着树滚下.如果 ...

  3. bzoj4458 GTY的OJ (优先队列+倍增)

    把超级钢琴放到了树上. 这次不用主席树了..本来以为会好写一点没想到细节更多(其实是树上细节多) 为了方便,对每个点把他的那个L,R区间转化成两个深度a,b,表示从[a,b)选一个最小的前缀和(到根的 ...

  4. 【BZOJ 3133】 3133: [Baltic2013]ballmachine (线段树+倍增)

    3133: [Baltic2013]ballmachine Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 148  Solved: 66 Descri ...

  5. [Baltic2013]ballmachine BZOJ3133

    分析: 我们考虑,因为每次放置的时候,都是向子树中含有的编号最小的哪一个走,那么放置的顺序是固定的,我们将边以to的子树最小排序,之后得到的出栈序就是球的放入顺序.目测可以使用堆来实现,线段树也能实现 ...

  6. BZOJ3133[Baltic2013]ballmachine

    题目描述 https://www.lydsy.com/JudgeOnline/problem.php?id=3133 题解 还是分两个操作来说吧. 先看第一个操作,放球,可以发现,对于祖先节点和后代节 ...

  7. Problem 1016 咒文卷轴 优先队列+前缀和+rmq

    题目链接: 题目 Problem 1016 咒文卷轴 Time Limit: 3000 mSec Memory Limit : 131072 KB 问题描述 小Y 是一个魔法师,有一天他获得了一卷神秘 ...

  8. BZOJ 4144 Dijkstra+Kruskal+倍增LCA

    思路: 先把所有的加油站 push进按weight排序的优先队列里 对于每个不是加油站的点 找到到它的点的最短路以及它来源的加油站 如果x和y有边 且x和y加油站的来源不一样 则它可以连边 跑一边Kr ...

  9. PAT1057 Stack(树状数组+倍增)

    目录 题目大意 题目分析 题目大意 要求维护一个栈,提供压栈.弹栈以及求栈内中位数的操作(当栈内元素\(n\)为偶数时,只是求第\(n/2\)个元素而非中间两数的平均值).最多操作100000次,压栈 ...

随机推荐

  1. 比官方文档更易懂的Vue.js教程!包你学会!

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由蔡述雄发表于云+社区专栏 蔡述雄,现腾讯用户体验设计部QQ空间高级UI工程师.智图图片优化系统首席工程师,曾参与<众妙之门> ...

  2. DSL 系列(1) - 扩展点的论述与实现

    前言 DSL 全称为 domain-specific language(领域特定语言),本系列应当会很长,其中包含些许不成熟的想法,欢迎私信指正. 1. DSL 简述 我理解的 DSL 的主要职能是 ...

  3. H5 颜色属性

    07-颜色属性 我是段落 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ...

  4. ubuntu中更改apache默认目录的方法

    如上,在这两个文件中,我都改为/home/www 及/home/www/html

  5. 文本文档中各字母出现次数汇总(java)

    package 字母频率统计; import java.io.*; public class Inputfile { public static void main(String args[]) { ...

  6. rbac组件权限按钮,菜单,可拔插

      1.通用模板 overflow: auto; //在a和b模板中进行切换 a 模板 :左侧菜单跟随滚动条 b模板  左侧以及上不动 **** <!DOCTYPE html> <h ...

  7. bat 文本合并

    小工具—把多个TXT文件合成一个 - TTXS_RS的博客 - CSDN博客https://blog.csdn.net/TTXS_RS/article/details/79743384 把所有文本文件 ...

  8. Jenkins Installing and migration

    JAVA_Zookeeper_hadoop - CSDN博客https://blog.csdn.net/wangmuming Installing Jenkins on Red Hat distrib ...

  9. 双击启动tomcat中的startup.bat闪退原因及解决方法

    免安装的tomcat双击startup.bat后,启动窗口一闪而过,而且tomcat服务未启动. 原因是:在启动tomcat是,需要读取环境变量和配置信息,缺少了这些信息,就不能登记环境变量,导致了t ...

  10. asp.net core下一个简单的分页技术

    在做web应用的时候免不了要对数据进行分页,我最近在做asp.net core的开发的时候就遇到了这个需求,现在简单的记录一下: public class PaginatedList<T> ...