【NOIP2016提高A组五校联考1】排队

来源:互联网 发布:骑士夺冠 知乎 编辑:程序博客网 时间:2024/05/18 09:07

Description

这里写图片描述

Solution

比赛的时候其实想到了正确的方法,但是以为这是错的,就没敢打。
首先可以用一个堆来维护空余的优先位置。
然后现在的问题就是,求一个点上面有多少个有值的点。
如果一个点对答案又贡献,那么它的子树的答案都要加1。那么维护dfs序的话,假设这棵子树的范围控制的是[x,y],那么就对x进行加1操作,y+1进行减1操作,然后如果要询问x的答案,那么直接在树状数组中的[0,x]的和就是了。

Code

#include<iostream>#include<cstdio>#include<cmath>#include<algorithm>#include<cstring>#include<queue>#define fo(i,a,b) for(i=a;i<=b;i++)#define fod(i,a,b) for(i=a;i>=b;i--)#define rep(i,a) for(i=first[a];i;i=next[i])using namespace std;const int maxn=200007;int i,j,k,l,n,m,ans,da,shu;int first[maxn*2],last[maxn*2],next[maxn*2],num,dfn;int ju[maxn];int first1[maxn*2],last1[maxn*2],next1[maxn*2],num1;int d[maxn],an[maxn],a[maxn],chu[maxn],jin[maxn];int f[maxn][21],g[maxn][21],dfx,tr[maxn],deep[maxn];bool bz[maxn];struct cmp1{    bool operator()(const int x,const int y) const{        return a[x]>a[y];    }};priority_queue<int,vector<int>, cmp1> t; struct node{    int a,b;}b[maxn];bool cmp(int x,int y){    return x>y;}void add(int x,int y){    last[++num]=y;next[num]=first[x],first[x]=num;}void add1(int x,int y){    last1[++num1]=y;next1[num1]=first1[x],first1[x]=num1;}void dfs1(int x,int y){    int i;f[x][0]=y;deep[x]=deep[y]+1;   jin[x]=++dfn;    rep(i,x){        if(last[i]!=y){            dfs1(last[i],x);        }    }    a[x]=++dfx;an[dfx]=x;    t.push(x);t.     chu[x]=dfn;}int lowbit(int x){return x&(-x);}void add2(int x,int y){    for(;x<=n;x+=lowbit(x))tr[x]+=y;}int find(int x){    int y=0;    for(;x;x-=lowbit(x))y+=tr[x];    return y;}int main(){//  freopen("fan.in","r",stdin);//  freopen("fan.out","w",stdout);    scanf("%d%d",&n,&m);    fo(i,1,n-1){        scanf("%d%d",&k,&l);        add1(k,l),add1(l,k);    }    fod(i,n,1){        d[0]=0;        for(j=first1[i];j;j=next1[j]){            if(last1[j]<i)d[++d[0]]=last1[j];        }        sort(d+1,d+1+d[0],cmp);        fo(j,1,d[0])add(i,d[j]),add(d[j],i);    }    dfs1(1,0);    fo(j,1,20)fo(i,1,n){        f[i][j]=f[f[i][j-1]][j-1];    }    shu=0;    while(m--){        scanf("%d%d",&k,&l);        if(k==1){            fo(i,1,l)ans=t.top(),add2(jin[t.top()],1),add2(chu[t.top()]+1,-1),t.pop();            printf("%d\n",ans);        }        else{            ans=0;            ans=find(jin[l]);ans--;            printf("%d\n",ans);             fod(i,20,0)            if((1<<i)<ans)l=f[l][i],ans-=(1<<i);            if(ans)l=f[l][0];            t.push(l);add2(jin[l],-1),add2(chu[l]+1,1);         }    }}
2 0
原创粉丝点击