Queue-jumpers HDU - 3436

http://acm.hdu.edu.cn/showproblem.php?pid=3436

伸展树离散化 将top和query查询的数存下来离散化 包括相邻两点中间产生的线段 并记录每个人在建树时对应的节点

若把某个人放到第一个位置 先收口袋 这样可以避免删节点后对其子节点的处理 再对剩余序列第一个位置收口袋 然后插入即可

看每个人在队列中的哪个位置 就把对应节点splay到根部 然后看左子树可以提供多少长度

看某个位置是哪个人 就不断二分 先看在不在当前节点 不在就看左右子树 在的话就看要找的位置减去左子树提供的长度后 咋当前节点什么位置 因为离散化后产生的这些线段内部位置是不会再发生变动的

#include <bits/stdc++.h>
using namespace std;

struct node0
{
    int l;
    int r;
};

struct node1
{
    int tp;
    int x;
};

struct node2;
node2 *null;

struct node2
{
    node2 *fa,*ch[2];
    int sz,len,l,r;
    void wipe()
    {
        fa=ch[0]=ch[1]=null;
        sz=1,len=0,l=0,r=-1;//
    }
    int getd()
    {
        return fa->ch[1]==this;
    }
    void setc(node2 *tmp,int d)
    {
        ch[d]=tmp;
        tmp->fa=this;
    }
    void pushup()
    {
        sz=ch[0]->sz+ch[1]->sz+1;
        len=(ch[0]->len+ch[0]->r-ch[0]->l+1)+(ch[1]->len+ch[1]->r-ch[1]->l+1);
    }
};

map <int,node2*> mp;
node0 pre[200010];
node1 order[100010];
node2 pool[200010];
node2 *root,*tail;
int tmp[100010];
int n,q,len,tot;

void build(node2 *&cur,node2 *fa,int l,int r)
{
    int m;
    if(l>r) return;
    m=(l+r)/2;
    cur=tail++;
    cur->wipe();
    cur->fa=fa;
    cur->l=pre[m].l,cur->r=pre[m].r;
    if(pre[m].l==pre[m].r) mp[pre[m].l]=cur;
    build(cur->ch[0],cur,l,m-1);
    build(cur->ch[1],cur,m+1,r);
    cur->pushup();
}

void init()
{
    node2 *tmp;
    tail=pool;
    null=tail++;
    null->fa=null->ch[0]=null->ch[1]=null;
    null->sz=0,null->len=0,null->l=0,null->r=-1;
    tmp=tail++;
    tmp->wipe();
    root=tmp;
    tmp=tail++;
    tmp->wipe();
    root->setc(tmp,1);
    mp.clear();
    build(root->ch[1]->ch[0],root->ch[1],1,tot);
    root->ch[1]->pushup();
    root->pushup();
}

void rotate(node2 *cur)
{
    node2 *f,*ff;
    int c,cc;
    f=cur->fa,ff=cur->fa->fa;
    c=cur->getd(),cc=f->getd();
    f->setc(cur->ch[!c],c);
    cur->setc(f,!c);
    if(ff->ch[cc]==f) ff->setc(cur,cc);
    else cur->fa=ff;
    f->pushup();
}

node2 *getpre(node2 *cur)
{
    cur=cur->ch[0];
    while(cur->ch[1]!=null) cur=cur->ch[1];
    return cur;
}

node2 *getnxt(node2 *cur)
{
    cur=cur->ch[1];
    while(cur->ch[0]!=null) cur=cur->ch[0];
    return cur;
}

node2 *getkth(node2 *cur,int k)
{
    while(cur->ch[0]->sz+1!=k)
    {
        if(cur->ch[0]->sz+1>k)
        {
            cur=cur->ch[0];
        }
        else
        {
            k-=(cur->ch[0]->sz+1);
            cur=cur->ch[1];
        }
    }
    return cur;
}

void splay(node2 *&root,node2 *tar,node2 *cur)
{
    while(cur->fa!=tar)
    {
        if(cur->fa->fa==tar) rotate(cur);
        else
        {
            if(cur->getd()==cur->fa->getd()) rotate(cur->fa);
            else rotate(cur);
            rotate(cur);
        }
    }
    cur->pushup();
    if(tar==null) root=cur;
}

int solve(node2 *cur,int x)
{
    //int cnt=0;
    while(!(cur->ch[0]->len+(cur->ch[0]->r-cur->ch[0]->l+1)+1<=x&&x<=cur->ch[0]->len+(cur->ch[0]->r-cur->ch[0]->l+1)+(cur->r-cur->l+1)))
    {
        //cnt++;
        //if(cnt<10) printf("^%d %d %d %d^\n",x,cur->l,cur->r,cur->len);
        if(cur->ch[0]->len+(cur->ch[0]->r-cur->ch[0]->l+1)+1>x) cur=cur->ch[0];
        else
        {
            x-=(cur->ch[0]->len+(cur->ch[0]->r-cur->ch[0]->l+1)+(cur->r-cur->l+1));
            cur=cur->ch[1];
        }
    }
    //printf("^%d %d %d %d^\n",x,cur->l,cur->r,cur->len);
    return cur->l+x-(cur->ch[0]->len+(cur->ch[0]->r-cur->ch[0]->l+1)+1);
}

void show()
{
    node2 *ptr;
    int i;
    printf("******\n");
    for(i=2;i<=tot+1;i++)
    {
        ptr=getkth(root,i);
        printf("%d %d %d\n",ptr->l,ptr->r,ptr->len);
    }
    printf("******\n");
}

int main()
{
    node2 *ptr0,*ptr1,*ptr2;
    int t,cas,i;
    char op[10];
    scanf("%d",&t);
    for(cas=1;cas<=t;cas++)
    {
        scanf("%d%d",&n,&q);
        len=0;
        for(i=1;i<=q;i++)
        {
            scanf("%s%d",op,&order[i].x);
            if(op[0]=='T') order[i].tp=0;
            else if(op[0]=='Q') order[i].tp=1;
            else order[i].tp=2;
            if(order[i].tp<=1) tmp[++len]=order[i].x;
        }
        tmp[++len]=1,tmp[++len]=n;
        sort(tmp+1,tmp+len+1);
        len=unique(tmp+1,tmp+len+1)-tmp-1;
        tot=0;
        for(i=1;i<=len;i++)
        {
            if(i>1&&tmp[i]-tmp[i-1]>1)
            {
                tot++;
                pre[tot].l=tmp[i-1]+1,pre[tot].r=tmp[i]-1;
            }
            tot++;
            pre[tot].l=tmp[i],pre[tot].r=tmp[i];
        }
        init();
        //show();
        printf("Case %d:\n",cas);
        for(i=1;i<=q;i++)
        {
            if(order[i].tp==0)
            {
                ptr0=mp[order[i].x];
                splay(root,null,ptr0);
                ptr1=getpre(ptr0);
                ptr2=getnxt(ptr0);
                //printf("^%d %d %d^\n",ptr1->l,ptr1->r,ptr1->len);
                //printf("^%d %d %d^\n",ptr2->l,ptr2->r,ptr2->len);
                splay(root,null,ptr1);
                splay(root,root,ptr2);
                root->ch[1]->ch[0]=null;
                root->ch[1]->pushup();
                root->pushup();

                ptr1=getkth(root,1);
                ptr2=getkth(root,2);
                splay(root,null,ptr1);
                splay(root,root,ptr2);
                root->ch[1]->setc(ptr0,0);
                root->ch[1]->pushup();
                root->pushup();
                //
            }
            else if(order[i].tp==1)
            {
                ptr0=mp[order[i].x];
                splay(root,null,ptr0);
                printf("%d\n",ptr0->ch[0]->len+(ptr0->ch[0]->r-ptr0->ch[0]->l+1)+1);
            }
            else
            {
                printf("%d\n",solve(root,order[i].x));
            }
            //show();
        }
    }
    return 0;
}

/*
3
7 4
Top 5
Top 2
Query 1
Rank 6
*/

猜你喜欢

转载自blog.csdn.net/sunyutian1998/article/details/81807666