3133: [Baltic2013]ballmachine

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 148  Solved: 66

Description

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

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

Input

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

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

Output

保证输入合法

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

Sample Input

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

Sample Output

1
3
2
2

HINT

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 (线段树+倍增)的更多相关文章

  1. bzoj 3779: 重组病毒 LCT+线段树+倍增

    题目: 黑客们通过对已有的病毒反编译,将许多不同的病毒重组,并重新编译出了新型的重组病毒.这种病毒的繁殖和变异能力极强.为了阻止这种病毒传播,某安全机构策划了一次实验,来研究这种病毒. 实验在一个封闭 ...

  2. isaster(Comet OJ - Contest #11D题+kruskal重构树+线段树+倍增)

    目录 题目链接 思路 代码 题目链接 传送门 思路 \(kruskal\)重构树\(+\)线段树\(+\)倍增 代码 #include <set> #include <map> ...

  3. [BZOJ 1483] [HNOI2009] 梦幻布丁 (线段树合并)

    [BZOJ 1483] [HNOI2009] 梦幻布丁 (线段树合并) 题面 N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1 ...

  4. [BZOJ 2653] middle(可持久化线段树+二分答案)

    [BZOJ 2653] middle(可持久化线段树+二分答案) 题面 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序 ...

  5. 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][ ...

  6. [BZOJ 3196] 213平衡树 【线段树套set + 树状数组套线段树】

    题目链接:BZOJ - 3196 题目分析 区间Kth和区间Rank用树状数组套线段树实现,区间前驱后继用线段树套set实现. 为了节省空间,需要离线,先离散化,这样需要的数组大小可以小一些,可以卡过 ...

  7. 【UOJ295】【ZJOI2017】线段树 倍增

    题目大意 http://uoj.ac/problem/295 题解 考虑像 zkw 线段树一样,从 \([l-1,l-1],[r+1,r+1]\) 这两个区间开始往上跳,直到两个指针碰到一起为止. 先 ...

  8. 2019.03.26 bzoj4444: [Scoi2015]国旗计划(线段树+倍增)

    传送门 题意简述:现在给你一个长度为mmm的环,有nnn条互不包含的线段,问如果强制选第iii条线段至少需要用几条线段覆盖这个环,注意用来的覆盖的线段应该相交,即[1,3],[4,5][1,3],[4 ...

  9. BZOJ.5286.[AHOI/HNOI2018]转盘(线段树)

    BZOJ LOJ 洛谷 如果从\(1\)开始,把每个时间\(t_i\)减去\(i\),答案取决于\(\max\{t_i-i\}\).记取得最大值的位置是\(p\),答案是\(t_p+1+n-1-p=\ ...

随机推荐

  1. .net core 中 identity server 4 之Topic --定义Client

    客户端指能够从id4获取Token的角色. 客户端的共性: a unique client ID a secret if needed the allowed interactions with th ...

  2. Goolge-Guava Concurrent中的Service

    最近在学习了下Google的Guava包,发现这真是一个好东西啊..由于平时也会写一些基于多线程的东西,所以特意了解了下这个Service框架.这里Guava包里的Service接口用于封装一个服务对 ...

  3. jQuery 写的简单打字游戏

    var off_x; //横坐标 var count=0; //总分 var speed=5000; //速度,默认是5秒. var keyErro=0; //输入错误次数 var keyRight= ...

  4. windows下gitlab配置 生成ssh key

    Git-1.9.5-preview20141217 1. 安装git,从程序目录打开 "Git Bash" 2. 键入命令:ssh-keygen -t rsa -C "e ...

  5. 原创:HTML 头像截取上传 JS+PHP 整合包~

    关于: 关于头像上传这个东西,网上一搜乱七八糟的一堆然而很少很少有自己中意的插件一怒之下就自己写一个... 用法: <!DOCTYPE html> <html lang=" ...

  6. POJ - 1330 Nearest Common Ancestors 最近公共祖先+链式前向星 模板题

    A rooted tree is a well-known data structure in computer science and engineering. An example is show ...

  7. CF 900B

    CF 900B Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u   Descript ...

  8. MongoDB之python简单交互(三)

    python连接mongodb有多种orm,主流的有pymongo和mongoengine. pymongo 安装相关模块 pip install pymongo pymongo操作 主要对象 Mon ...

  9. flask插件系列之SQLAlchemy实用技巧

    下面记录一下SQLAlchemy使用的技巧. 在多模块下定义models 如果由多个蓝图下读定义了model模块,在初始化的时候需要加载到上下文中. 当使用flask_Migrate迁移数据库的时候, ...

  10. AWS 使用总结

    A.升配置的流程: 1.新开一台配置较高的机器; 2.将新机器和老机器的磁盘都取消关联,注意需要记录下老机器的磁盘分区设备名,如:/dev/sda1: 3.将老机器的磁盘挂载到新机器上,磁盘分区设备名 ...