Luogu P1503 鬼子进村(平衡树+栈)

这篇博客介绍了一种利用栈和平衡树(splay tree)数据结构处理包括插入、删除和查找操作的序列的方法。主要涉及AC自动机算法,通过ACCode展示了如何在C++中实现这些操作,用于解决特定的编程问题。
摘要由CSDN通过智能技术生成

在这里插入图片描述

思路:

前面两个操作自然想到可以用栈模拟,然后可以把摧毁了的房子加到平衡树中。操作三的话只要找到前驱和后继即可,last-pre-1即为答案。

AC Code

#include<bits/stdc++.h>
using namespace std;
const int N=5e4+10;
struct splay_tree
{
    int ff,ch[2],val,size;
}tr[N];
int root,tot;
void update(int x)
{
    tr[x].size=tr[tr[x].ch[0]].size+tr[tr[x].ch[1]].size;
}
void rotate(int x)
{
    int y=tr[x].ff;
    int z=tr[y].ff;
    int k=(tr[y].ch[1]==x);
    tr[z].ch[(tr[z].ch[1]==y)]=x;
    tr[x].ff=z;
    tr[y].ch[k]=tr[x].ch[k^1]; 
    tr[tr[x].ch[k^1]].ff=y;
    tr[x].ch[k^1]=y;
    tr[y].ff=x; 
    update(y);
    update(x);
}
void splay(int x,int s)
{
    while(tr[x].ff!=s)
    {
        int y=tr[x].ff;
        int z=tr[y].ff;
        if(z!=s)
            (tr[z].ch[0]==y)^(tr[y].ch[0]==x)?rotate(x):rotate(y);
        rotate(x);
    }
    if(s==0) root=x;
}
void find(int x)
{
    int u=root;
    if(!u) return ;
    while(tr[u].ch[x>tr[u].val]&&x!=tr[u].val)
        u=tr[u].ch[x>tr[u].val];
    splay(u,0);
}
void insert(int x)
{
    int u=root,ff=0;
    while(u&&tr[u].val!=x)
    {
        ff=u;
        u=tr[u].ch[x>tr[u].val];
    }
    u=++tot;
    if(ff) tr[ff].ch[x>tr[ff].val]=u;
    tr[u].ch[0]=tr[u].ch[1]=0;
    tr[tot].ff=ff;
    tr[tot].val=x;
    tr[tot].size=1;
    splay(u,0);
}
int Next(int x,int f)
{
    find(x);
    int u=root;
    if(tr[u].val>x&&f)
        return u;
    if(tr[u].val<x&&!f)
        return u;
    u=tr[u].ch[f];
    while(tr[u].ch[f^1])
        u=tr[u].ch[f^1];
    return u;
}
void Delete(int x)
{
    int last=Next(x,0);
    int Net=Next(x,1);
    splay(last,0);
    splay(Net,last);
    int del=tr[Net].ch[0];
    tr[Net].ch[0]=0;
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    insert(0);
    insert(n+1);
    stack<int>st;
    while(m--)
    {
        char op;
        cin>>op;
        if(op=='D')
        {
            int x;
            scanf("%d",&x);
            insert(x);
            st.push(x);
        }
        else if(op=='R')
        {
            if(st.empty()) continue;
            int x=st.top();
            st.pop();
            Delete(x);
        }
        else
        {
            int x;
            scanf("%d",&x);
            find(x);
            if(tr[root].val==x) printf("0\n");
            else
            {
                int a=Next(x,0);
                int b=Next(x,1);
                printf("%d\n",tr[b].val-tr[a].val-1);
            }
        }
    }
    //system("pause");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值