zoukankan      html  css  js  c++  java
  • luogu1503

    P1503 鬼子进村

    题目背景

    小卡正在新家的客厅中看电视。电视里正在播放放了千八百次依旧重播的《亮剑》,剧中李云龙带领的独立团在一个县城遇到了一个鬼子小队,于是独立团与鬼子展开游击战。

    题目描述

    描述 县城里有n个用地道相连的房子,第i个只与第i-1和第i+1个相连。这是有m个消息依次传来

    1、消息为D x:鬼子将x号房子摧毁了,地道被堵上。

    2、消息为R :村民们将鬼子上一个摧毁的房子修复了。

    3、消息为Q x:有一名士兵被围堵在x号房子中。

    李云龙收到信息很紧张,他想知道每一个被围堵的士兵能够到达的房子有几个。

    输入输出格式

    输入格式:

     

    第一行2个整数n,m(n,m<=50000)。

    接下来m行,有如题目所说的三种信息共m条。

     

    输出格式:

     

    对于每一个被围堵的士兵,输出该士兵能够到达的房子数。

    输入输出样例

    输入样例#1: 
    7 9
    D 3
    D 6
    D 5
    Q 4
    Q 5
    R
    Q 4
    R
    Q 4
    
    输出样例#1: 
    1
    0
    2
    4
    

    说明

    若士兵被围堵在摧毁了的房子中,那只能等死了。。。。。。

    sol:对于R显然可以用一个栈来搞一搞。难点是另两个

    对于每个D,如果那个点不在栈里就插入那个点

    对于A,我们查询那个点的后继和前驱,减一下就可以了

    Ps:说起来容易,写起来真操蛋

    #include <bits/stdc++.h>
    using namespace std;
    typedef int ll;
    inline ll read()
    {
        ll s=0;
        bool f=0;
        char ch=' ';
        while(!isdigit(ch))
        {
            f|=(ch=='-'); ch=getchar();
        }
        while(isdigit(ch))
        {
            s=(s<<3)+(s<<1)+(ch^48); ch=getchar();
        }
        return (f)?(-s):(s);
    }
    #define R(x) x=read()
    inline void write(ll x)
    {
        if(x<0)
        {
            putchar('-'); x=-x;
        }
        if(x<10)
        {
            putchar(x+'0');    return;
        }
        write(x/10);
        putchar((x%10)+'0');
        return;
    }
    #define W(x) write(x),putchar(' ')
    #define Wl(x) write(x),putchar('
    ')
    const int N=50005;
    int n,Q;
    namespace Pht
    {
        int Points=0,Root;
        int Child[N][2],Parent[N];
        int Size[N];
        int Pos[N]; //Pos[i]表示标号为i的节点在平衡树上的位置
        int Id[N]; //Id[i]表示树上的节点i的标号为i 
        
        int Stack[N],Top=0;
        bool Instack[N];
        
        inline void Init();
        inline int Check(int x);
        inline void PushUp(int x);
        inline void Rotate(int x);
        inline void Splay(int At,int To);
        inline void Insert(int Val);
        inline void Remove(int Val);
        inline int Find(int Val);
        inline int Ask_Upper(int Val);
        inline int Ask_Lower(int Val);
        
        inline void Init()
        {
            Points=Root=0;
            Insert(0); Insert(n+1);
        }
        inline int Check(int x)
        {
            return (Child[Parent[x]][0]==x)?0:1;
        }
        inline void PushUp(int x)
        {
            Size[x]=Size[Child[x][0]]+Size[Child[x][1]]+1;
            Pos[Id[Child[x][0]]]=Child[x][0];
            Pos[Id[Child[x][1]]]=Child[x][1];
        }
        inline void Rotate(int x)
        {
            int y,z,oo;
            y=Parent[x];
            z=Parent[y];
            oo=Check(x);
            Child[y][oo]=Child[x][oo^1]; Parent[Child[x][oo^1]]=y;
            Child[z][Check(y)]=x; Parent[x]=z;
            Child[x][oo^1]=y; Parent[y]=x;
            PushUp(x); PushUp(y);
        }
        inline void Splay(int At,int To)
        {
            while(Parent[At]!=To)
            {
                int Father=Parent[At];
                if(Parent[Father]==To)
                {
                    Rotate(At);
                }
                else if(Check(At)==Check(Father))
                {
                    Rotate(Father); Rotate(At);
                }
                else
                {
                    Rotate(At); Rotate(At);
                }
            }
            Pos[Id[At]]=At;
            if(To==0) Root=At;
        }
        inline void Insert(int Val)
        {
            int Now=Root,Par=0;
            while(Now)
            {
                Par=Now;
                Now=Child[Now][(Val>Id[Now])?1:0];
            }
            Now=++Points;
            if(Par) Child[Par][(Val>Id[Par])?1:0]=Now;
            Parent[Now]=Par;
            Child[Now][0]=Child[Now][1]=0;
            Size[Now]=1;
            Id[Now]=Val;
            Pos[Val]=Now;
            Splay(Now,0);
        }
        inline void Remove(int Val)
        {
    //        printf("Val=%d
    ",Val);
            int Lower=Ask_Lower(Val);
    //        printf("Lower=%d
    ",Lower);
            int Upper=Ask_Upper(Val);
    //        printf("Upper=%d
    ",Upper);
            Splay(Lower,0);
            Splay(Upper,Lower);
            Pos[Id[Child[Upper][0]]]=0;
            Id[Child[Upper][0]]=-1;
            Child[Upper][0]=0;
        }
        inline int Find(int Val)
        {
            int Now=Root;
            while(Now&&(Id[Now]!=Val))
            {
                Now=Child[Now][(Val>Id[Now])?1:0];
            }
            return Now;
        }
        inline int Ask_Lower(int Val)
        {
            int Pos=Find(Val);
    //        printf("Pos=%d
    ",Pos);
            Splay(Pos,0);
    //        puts("End-Splay");
            int Now=Root;
            Now=Child[Now][0];
            while(Child[Now][1]) Now=Child[Now][1];
            return Now;
        }
        inline int Ask_Upper(int Val)
        {
            int Pos=Find(Val);
            Splay(Pos,0);
            int Now=Root;
            Now=Child[Now][1];
            while(Child[Now][0]) Now=Child[Now][0];
            return Now;
        }
        inline void Solve()
        {
            Init();
            while(Q--)
            {
                int x;
                char ch=' '; while(!isupper(ch)) ch=getchar();
                switch(ch)
                {
                    case 'D':
                        R(x);
                        if(!Instack[x])
                        {
                            Stack[++Top]=x;
                            Instack[x]=1;
                            Insert(x);
                        }
                        break;
                    case 'R':
                        Instack[Stack[Top]]=0;
                        Remove(Stack[Top--]);
                        break;
                    case 'Q':
                        R(x);
                        if(Instack[x]) puts("0");
                        else
                        {
                            Insert(x);
                            Wl(Id[Ask_Upper(x)]-Id[Ask_Lower(x)]-1);
                            Remove(x);
                        }
                        break;
                }
            }
        }
    }
    int main()
    {
        R(n); R(Q);
        Pht::Solve();
        return 0;
    }
    /*
    input
    7 9
    D 3
    D 6
    D 5
    Q 4
    Q 5
    R
    Q 4
    R
    Q 4
    output
    1
    0
    2
    4
    */
    View Code
  • 相关阅读:
    delphi 让子窗体显示最大化
    Delphi 中拖动无边框窗口的5种方法
    Delphi 非主窗体(即子窗体)在任务栏显示按钮
    电脑快捷键大全
    picpick快捷键
    is()
    animate()
    :animated
    css() 方法返回或设置匹配的元素的一个或多个样式属性。
    outerWidth()
  • 原文地址:https://www.cnblogs.com/gaojunonly1/p/10692934.html
Copyright © 2011-2022 走看看