[BZOJ3133] [Baltic2013] ballmachine (+ tree multiplier stack)

[BZOJ3133] [Baltic2013] ballmachine (+ tree multiplier stack)

Face questions

There is a ball machine, it can be seen as a tree structure. There are the following two operations:

From the root into a ball, as long as there is space underneath, will the ball rolling down the tree. If there are multiple points can go, then choose the direction of the path of least where the number of nodes. In the example, the root successively 4put two balls, a ball will fall into the first 1, the second will fall 3:

img

Took a ball from a certain position, then it will fall to the top of the ball. For example, in order to take away 5, 7, 8three goals:

img

analysis

We can pre-discharge when the i-th from the root ball, the ball reaches the position x. Thus, for each node x, we put the first few records when the ball falls to x, denoted seq [x].

When the first pre-dfs again, obtaining the lowest node number of each node in the subtree. Dfs and then again, in accordance with the smallest sub-tree node number from small to large to traverse. The direct adjacency list can sort it again. Easy to find, seq [x] is the x in the first few tree traversal sequence after sequence (because the ball will try to go to the bottom)

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;
}

Then consider the dynamic insertion and deletion.

Maintain a minimum heap, top of the heap meet the minimum elements seq. Insertion of the top of the stack pop, the top of the stack corresponding to the state node labeled ball.

Remove node x, x root node to node on the chain would fall to the floor. Therefore only need to find a tree multiplier x ancestry in the shallowest ball node, its status is marked as the ball, and then insert the minimum heap.

Code

#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));
    }
}

Guess you like

Origin www.cnblogs.com/birchtree/p/11518542.html