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

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求,这个我用倍增搞的。

  就这样啊。不要看错题就好了啊。

 

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<vector>
  7 using namespace std;
  8 #define Maxn 100010
  9 
 10 int mymin(int x,int y) {return x<y?x:y;}
 11 
 12 struct node
 13 {
 14     int x,y,next;
 15 }t[Maxn*2];
 16 int first[Maxn],len;
 17 
 18 void ins(int x,int y)
 19 {
 20     t[++len].x=x;t[len].y=y;
 21     t[len].next=first[x];first[x]=len;
 22 }
 23 
 24 int dfn[Maxn],fn[Maxn],c[Maxn],fa[Maxn],dep[Maxn],mn[Maxn],cnt=0;
 25 int ff[Maxn][20];
 26 bool p[Maxn];
 27 
 28 void dfs1(int x)
 29 {
 30     mn[x]=x;
 31     for(int i=first[x];i;i=t[i].next) if(t[i].y!=fa[x])
 32     {
 33         int y=t[i].y;
 34         dfs1(y);
 35         mn[x]=mymin(mn[x],mn[y]);
 36     }
 37 }
 38 
 39 bool cmp(int x,int y) {return mn[x]<mn[y];}
 40 
 41 int son[Maxn];
 42 void dfs(int x)
 43 {
 44     dep[x]=dep[fa[x]]+1;
 45     int st=son[0],ed;
 46     for(int i=first[x];i;i=t[i].next) if(t[i].y!=fa[x])
 47     {
 48         int y=t[i].y;
 49         son[++son[0]]=y;
 50     }ed=son[0];
 51     sort(son+st+1,son+1+ed,cmp);
 52     for(int i=st+1;i<=ed;i++) dfs(son[i]);
 53     dfn[x]=++cnt;
 54     fn[cnt]=x;
 55 }
 56 
 57 
 58 struct nnode
 59 {
 60     int l,r,lc,rc,sm;
 61 }tr[Maxn*2];
 62 
 63 int tot=0;
 64 int build(int l,int r)
 65 {
 66     int x=++tot;
 67     tr[x].l=l;tr[x].r=r;tr[x].sm=0;
 68     if(l!=r)
 69     {
 70         int mid=(l+r)>>1;
 71         tr[x].lc=build(l,mid);
 72         tr[x].rc=build(mid+1,r);
 73     }
 74     else tr[x].lc=tr[x].rc=0;
 75     return x;
 76 }
 77 
 78 void change(int x,int y,int z)
 79 {
 80     if(tr[x].l==tr[x].r)
 81     {
 82         tr[x].sm=z;
 83         return;
 84     }
 85     int mid=(tr[x].l+tr[x].r)>>1;
 86     if(y<=mid) change(tr[x].lc,y,z);
 87     else change(tr[x].rc,y,z);
 88     tr[x].sm=tr[tr[x].lc].sm+tr[tr[x].rc].sm;
 89 }
 90 
 91 int query(int x)
 92 {
 93     if(tr[x].l==tr[x].r) return tr[x].l;
 94     int lc=tr[x].lc,rc=tr[x].rc;
 95     int mid=(tr[x].l+tr[x].r)>>1;
 96     if(tr[lc].sm<mid-tr[x].l+1) return query(tr[x].lc);
 97     return query(tr[x].rc);
 98 }
 99 
100 int ffind(int x)
101 {
102     for(int j=18;j>=0;j--) if(ff[x][j]&&p[ff[x][j]]) 
103         x=ff[x][j];
104     return x;
105 }
106 
107 int main()
108 {
109     int n,q;
110     scanf("%d%d",&n,&q);
111     len=0;
112     memset(first,0,sizeof(first));
113     int rt=0;
114     for(int i=1;i<=n;i++)
115     {
116         int x;
117         scanf("%d",&x);
118         fa[i]=x;
119         if(x==0) rt=i;
120         else ins(x,i);
121     }
122     for(int i=1;i<=n;i++) ff[i][0]=fa[i];
123     for(int i=1;i<=n;i++) p[i]=0;
124     for(int j=1;(1<<j)<=n;j++)
125      for(int i=1;i<=n;i++)
126         ff[i][j]=ff[ff[i][j-1]][j-1];
127     dep[0]=0;
128     dfs1(rt);
129     son[0]=0;dfs(rt);
130     build(1,n);
131     for(int i=1;i<=q;i++)
132     {
133         int op,x;
134         scanf("%d%d",&op,&x);
135         if(op==1)
136         {
137             while(x--)
138             {
139                 int y=query(1);
140                 change(1,y,1);
141                 p[fn[y]]=1;
142                 if(x==0) printf("%d\n",fn[y]);
143             }
144         }
145         else
146         {
147             if(!p[x]) continue;
148             int y=ffind(x);
149             change(1,dfn[y],-1);
150             p[y]=0;
151             printf("%d\n",dep[x]-dep[y]);
152         }
153     }
154     return 0;
155 }
View Code

 

2017-03-26 20:30:43

posted @ 2017-03-26 20:30  konjak魔芋  阅读(325)  评论(0编辑  收藏  举报