【JZOJ4811】排队

来源:互联网 发布:淘宝主图背景素材psd 编辑:程序博客网 时间:2024/05/22 06:29

Description

这里写图片描述

Solution

明确一点,每个人进入的地方优先级是确定的。

那么我们一开始把所有房间的优先级求出来,塞进堆里。

对于操作一,一个个把有人的房间从堆中弹出。

对于操作二,倍增找到根到当前房间第一个有人的房间,重新加入堆即可。答案即为两房间深度差。

Code

#include<iostream>#include<cstdio>#include<cstdlib>#include<queue>#include<algorithm>#define fo(i,j,k) for(int i=j;i<=k;i++)#define fd(i,j,k) for(int i=j;i>=k;i--)#define ll long long#define N 100001#define M 200001#define inf 2147483647using namespace std;int to[M],next[M],last[M],num=0;int fa[N],f[N][18];int d[N];int n;struct node{    friend bool operator< (node x,node y)    {        return x.p>y.p;    }    int p,z;}c[N];void link(int x,int y){    num++;    to[num]=y;    next[num]=last[x];    last[x]=num;}bool bz[N];int tot=0;priority_queue<node> q;priority_queue<int, vector<int>, greater<int> > qn[N];void find(int x){    for(int i=last[x];i;i=next[i])    {        int v=to[i];        if(v!=fa[x])        {            fa[v]=x;            f[v][0]=x;            d[v]=d[x]+1;            qn[x].push(v);        }    }    while(!qn[x].empty())    {        find(qn[x].top());        qn[x].pop();    }    node b;    b.z=x;    b.p=++tot;    q.push(b);    c[x]=b;}int main(){    int qq;    cin>>n>>qq;    fo(i,1,n-1)    {        int x,y;        scanf("%d %d",&x,&y);        link(x,y);        link(y,x);    }    d[0]=-1;    find(1);    fo(j,1,17)    fo(i,1,n) f[i][j]=f[f[i][j-1]][j-1];    while(qq--)    {        int op,x;        scanf("%d %d",&op,&x);        if(op==1)        {            fo(i,1,x-1)            {                bz[q.top().z]=1;                q.pop();            }            bz[q.top().z]=1;            printf("%d\n",q.top().z);            q.pop();        }        else        {            int p=x;            fd(i,17,0)            if(f[p][i] && bz[f[p][i]]) p=f[p][i];            bz[p]=0;            if(p!=x) bz[x]=1;            printf("%d\n",d[x]-d[p]);            q.push(c[p]);        }    }}
1 0
原创粉丝点击