【BZOJ 3133】 3133: [Baltic2013]ballmachine (线段树+倍增)
3133: [Baltic2013]ballmachine
Time Limit: 20 Sec Memory Limit: 128 MB
Submit: 148 Solved: 66Description
有一个装球机器,构造可以看作是一棵树。有下面两种操作:
- 从根放入一个球,只要下方有空位,球会沿着树滚下。如果同时有多个点可以走,那么会选择编号最小的节点所在路径的方向。比如依次在树根
4放2个球,第一个球会落到1,第二个会落到3:
- 从某个位置拿走一个球,那么它上方的球会落下来。比如依次拿走
5, 7, 8三个球:
Input
第一行:球的个数
N,操作个数Q(N, Q <= 100 000)下面N行:第i个节点的父亲。如果是根,则为0接下来Q行:op num
op == 1:在根放入num个球op == 2:拿走在位置num的球Output
保证输入合法
op == 1:输出最后一个球落到了哪里op == 2:输出拿走那个球后有多少个球会掉下来Sample Input
8 4
0
1
2
2
3
3
4
6
1 8
2 5
2 7
2 8Sample Output
1
3
2
2HINT
Source
【分析】
没什么人发题解。。
像我一样看错题的同学看看discuss。。【可怜我只看了样例,然后出的数据对拍的全是祖先的id小于儿子的,就什么也没发现。。
首先,按照收球顺序弄到dfn,然后每次就是问没有放球的dfn最小的嘛,就用线段树搞这个就好了。【一开始想二分+前缀和logn^2真是很搞笑。。
第二个拿东西,就是相当于把x往上走最后一个有东西的放到x那里,掉了多少个就用dep求,这个我用倍增搞的。
就这样啊。不要看错题就好了啊。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
#define Maxn 100010 int mymin(int x,int y) {return x<y?x:y;} struct node
{
int x,y,next;
}t[Maxn*];
int first[Maxn],len; void ins(int x,int y)
{
t[++len].x=x;t[len].y=y;
t[len].next=first[x];first[x]=len;
} int dfn[Maxn],fn[Maxn],c[Maxn],fa[Maxn],dep[Maxn],mn[Maxn],cnt=;
int ff[Maxn][];
bool p[Maxn]; void dfs1(int x)
{
mn[x]=x;
for(int i=first[x];i;i=t[i].next) if(t[i].y!=fa[x])
{
int y=t[i].y;
dfs1(y);
mn[x]=mymin(mn[x],mn[y]);
}
} bool cmp(int x,int y) {return mn[x]<mn[y];} int son[Maxn];
void dfs(int x)
{
dep[x]=dep[fa[x]]+;
int st=son[],ed;
for(int i=first[x];i;i=t[i].next) if(t[i].y!=fa[x])
{
int y=t[i].y;
son[++son[]]=y;
}ed=son[];
sort(son+st+,son++ed,cmp);
for(int i=st+;i<=ed;i++) dfs(son[i]);
dfn[x]=++cnt;
fn[cnt]=x;
} struct nnode
{
int l,r,lc,rc,sm;
}tr[Maxn*]; int tot=;
int build(int l,int r)
{
int x=++tot;
tr[x].l=l;tr[x].r=r;tr[x].sm=;
if(l!=r)
{
int mid=(l+r)>>;
tr[x].lc=build(l,mid);
tr[x].rc=build(mid+,r);
}
else tr[x].lc=tr[x].rc=;
return x;
} void change(int x,int y,int z)
{
if(tr[x].l==tr[x].r)
{
tr[x].sm=z;
return;
}
int mid=(tr[x].l+tr[x].r)>>;
if(y<=mid) change(tr[x].lc,y,z);
else change(tr[x].rc,y,z);
tr[x].sm=tr[tr[x].lc].sm+tr[tr[x].rc].sm;
} int query(int x)
{
if(tr[x].l==tr[x].r) return tr[x].l;
int lc=tr[x].lc,rc=tr[x].rc;
int mid=(tr[x].l+tr[x].r)>>;
if(tr[lc].sm<mid-tr[x].l+) return query(tr[x].lc);
return query(tr[x].rc);
} int ffind(int x)
{
for(int j=;j>=;j--) if(ff[x][j]&&p[ff[x][j]])
x=ff[x][j];
return x;
} int main()
{
int n,q;
scanf("%d%d",&n,&q);
len=;
memset(first,,sizeof(first));
int rt=;
for(int i=;i<=n;i++)
{
int x;
scanf("%d",&x);
fa[i]=x;
if(x==) rt=i;
else ins(x,i);
}
for(int i=;i<=n;i++) ff[i][]=fa[i];
for(int i=;i<=n;i++) p[i]=;
for(int j=;(<<j)<=n;j++)
for(int i=;i<=n;i++)
ff[i][j]=ff[ff[i][j-]][j-];
dep[]=;
dfs1(rt);
son[]=;dfs(rt);
build(,n);
for(int i=;i<=q;i++)
{
int op,x;
scanf("%d%d",&op,&x);
if(op==)
{
while(x--)
{
int y=query();
change(,y,);
p[fn[y]]=;
if(x==) printf("%d\n",fn[y]);
}
}
else
{
if(!p[x]) continue;
int y=ffind(x);
change(,dfn[y],-);
p[y]=;
printf("%d\n",dep[x]-dep[y]);
}
}
return ;
}
2017-03-26 20:30:43
【BZOJ 3133】 3133: [Baltic2013]ballmachine (线段树+倍增)的更多相关文章
- bzoj 3779: 重组病毒 LCT+线段树+倍增
题目: 黑客们通过对已有的病毒反编译,将许多不同的病毒重组,并重新编译出了新型的重组病毒.这种病毒的繁殖和变异能力极强.为了阻止这种病毒传播,某安全机构策划了一次实验,来研究这种病毒. 实验在一个封闭 ...
- isaster(Comet OJ - Contest #11D题+kruskal重构树+线段树+倍增)
目录 题目链接 思路 代码 题目链接 传送门 思路 \(kruskal\)重构树\(+\)线段树\(+\)倍增 代码 #include <set> #include <map> ...
- [BZOJ 1483] [HNOI2009] 梦幻布丁 (线段树合并)
[BZOJ 1483] [HNOI2009] 梦幻布丁 (线段树合并) 题面 N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1 ...
- [BZOJ 2653] middle(可持久化线段树+二分答案)
[BZOJ 2653] middle(可持久化线段树+二分答案) 题面 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序 ...
- bzoj 1537: [POI2005]Aut- The Bus 线段树
bzoj 1537: [POI2005]Aut- The Bus 先把坐标离散化 设f[i][j]表示从(1,1)走到(i,j)的最优解 这样直接dp::: f[i][j] = max{f[i-1][ ...
- [BZOJ 3196] 213平衡树 【线段树套set + 树状数组套线段树】
题目链接:BZOJ - 3196 题目分析 区间Kth和区间Rank用树状数组套线段树实现,区间前驱后继用线段树套set实现. 为了节省空间,需要离线,先离散化,这样需要的数组大小可以小一些,可以卡过 ...
- 【UOJ295】【ZJOI2017】线段树 倍增
题目大意 http://uoj.ac/problem/295 题解 考虑像 zkw 线段树一样,从 \([l-1,l-1],[r+1,r+1]\) 这两个区间开始往上跳,直到两个指针碰到一起为止. 先 ...
- 2019.03.26 bzoj4444: [Scoi2015]国旗计划(线段树+倍增)
传送门 题意简述:现在给你一个长度为mmm的环,有nnn条互不包含的线段,问如果强制选第iii条线段至少需要用几条线段覆盖这个环,注意用来的覆盖的线段应该相交,即[1,3],[4,5][1,3],[4 ...
- BZOJ.5286.[AHOI/HNOI2018]转盘(线段树)
BZOJ LOJ 洛谷 如果从\(1\)开始,把每个时间\(t_i\)减去\(i\),答案取决于\(\max\{t_i-i\}\).记取得最大值的位置是\(p\),答案是\(t_p+1+n-1-p=\ ...
随机推荐
- 机器学习-kNN-寻找最好的超参数
一 .超参数和模型参数 超参数:在算法运行前需要决定的参数 模型参数:算法运行过程中学习的参数 - kNN算法没有模型参数- kNN算法中的k是典型的超参数 寻找好的超参数 领域知识 经验数值 实验搜 ...
- TinyOS 代码分析
1.Basestation案例 位于/opt/tinyos-main-master/apps/Basetation 1.1本例的顶层结构图: 1.2软件实现流程 1) uartIn,uartOut ...
- win10环境变量
jdk8 JAVA_HOME D:\devsoft\jdk\jdk1.8 CLASSPATH .;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar pa ...
- xss自动化攻击
所需工具 [1.xssValidator] [2.phantomjs] [3.xss.js] /** * This is a basic phantomJS script that will be u ...
- git服务器的简单搭建
安装git 安装git,参考:https://git-scm.com/book/zh/v1/%E8%B5%B7%E6%AD%A5-%E5%AE%89%E8%A3%85-Git 创建git仓库 使用ro ...
- 修改 firefox accesskey 的快捷键
Chrome中,如果设置了 accesskey 的话,可以通过 Alt + 快捷键 来之直接跳转的.但在Firefox 中,可能是为了防止于菜单的快捷键冲突,所以设置了 Shift + Alt + 快 ...
- AJP与HTTP比较和分析
系统环境: OS:Ubuntu 10.10 (2G) Servlet Container:tomcat-tomcat-7.0.23 (最大内存:default 256M maxThreads:50 ...
- 记点事! oracle 调用外部命令
oracle执行系统命令 测试成功环境:windows XP+oracle 10g.window 2008 R2 + 11g 代码如下: www.2cto.com Sql代码 crea ...
- POJ 3159 Candies(差分约束+spfa+链式前向星)
题目链接:http://poj.org/problem?id=3159 题目大意:给n个人派糖果,给出m组数据,每组数据包含A,B,C三个数,意思是A的糖果数比B少的个数不多于C,即B的糖果数 - A ...
- Valid Sudoku&&Sudoku Solver
Valid Sudoku Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. The Sudoku bo ...
.jpg)
.jpg)