【JZOJ 4811】排队

Description

这里写图片描述

Solution

先一问一问来,
对于第一问,先给每个点一个优先值,很显然每个点的优先值都是一定的,每次一定选优先值最大的点,然后删掉。这个可以用堆(C++有优先队列)来实现,
对于第二问,很显然删除当前点后,移动的点一定是连续的,所以直接用LCA跳即可,

复杂度: O(nlog(n))

Code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define efo(i,q) for(int i=A[q];i;i=B[i][0])
#define iff() if(B[i][1]!=fa)
using namespace std;
const int N=100500;
int read(int &n)
{
    char ch=' ';int q=0,w=1;
    for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
    if(ch=='-')w=-1,ch=getchar();
    for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int m,n,ans;
bool Z[N];
int G[N][21],C[N],No[N];
int B[2*N][2],A[N],B0;
struct wq{int q,w;}SC[N*2];
struct qqww
{
    int n;
    friend bool operator <(qqww q,qqww w){return No[q.n]>No[w.n];}
}cty;
priority_queue<qqww>d;
bool PX(wq q,wq w){return q.q>w.q||(q.q==w.q&&q.w>w.w);}
void link(int q,int w){B[++B0][0]=A[q];A[q]=B0,B[B0][1]=w;}
void dfs(int q,int fa,int c)
{
    G[q][0]=fa,C[q]=c;
    efo(i,q)
        iff()dfs(B[i][1],q,c+1);
    No[q]=++No[0];
}
int find(int q)
{
    while(Z[G[q][0]])
    {
        int I=0;
        while(Z[G[G[q][I+1]][0]])I++;
        q=G[q][I];
    }
    return q;
}
int main()
{
    int q,w,_;
    read(n),read(_);
    fo(i,1,n-1)SC[i+n-1].w=read(SC[i].q),SC[i+n-1].q=read(SC[i].w);
    sort(SC+1,SC+2*n-1,PX);
    fo(i,1,2*n-2)link(SC[i].q,SC[i].w);
    dfs(1,0,1);
    fo(j,1,20)fo(i,1,n)G[i][j]=G[G[i][j-1]][j-1];
    fo(i,1,n)cty.n=i,d.push(cty);
    while(_--)
    {
        read(w),read(q);
        if(w-1)
        {
            w=find(q);
            printf("%d\n",C[q]-C[w]);
            Z[w]=0;cty.n=w;
            d.push(cty);
        }
        else 
        {
            w=q;
            while(w--)
            {
                cty=d.top();
                Z[cty.n]=1;
                d.pop();
            }
            printf("%d\n",cty.n);
        }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值