luogu P3797 妖梦斩木棒

 二次联通门 : luogu P3797 妖梦斩木棒

 

 

 

/*
    luogu P3797 妖梦斩木棒
    
        建一棵线段树,维护

        1.有几段完整的木棍,

        2.左边是否有向右边的开口,

        3.右边是否有向左边的开口,

        4.以及是否完全无开口(全为'X')(便于区间合并)。
*/
#include <cstdio>

void read (int &now)
{
    now = 0;
    register char word = getchar ();
    while (word < '0' || word > '9')
        word = getchar ();
    while (word >= '0' && word <= '9')
    {
        now = now * 10 + word - '0';
        word = getchar ();
    }
}

int N, M;

struct S_D
{
    
    S_D *Left, *Right;
    
    bool key;
    bool Bracket_L, Bracket_R;
    
    int value;
    
    int l, r;
    int Mid;
    
    inline void F_Updata (bool now_1, bool now_2, bool now)
    {
        Bracket_L = now_1;
        Bracket_R = now_2;
        key = now;
        value = 0;
    }
    
    S_D (int __l, int __r) : l (__l), r (__r)
    {
        Left = Right = NULL;
        
        Mid = __l + __r >> 1;
        key = false;
        value = 0;
        Bracket_L = Bracket_R = false;
    }
    
    S_D ()
    {
        Left = Right = NULL;
        Bracket_L = Bracket_R = false;
        key = false;
        
        value = 0;
    }
    
    inline void Up ()
    {
        this->key = this->Left->key & this->Right->key;
        
        this->Bracket_L = this->Left->key ? this->Right->Bracket_L : this->Left->Bracket_L;
        this->Bracket_R = this->Right->key ? this->Left->Bracket_R : this->Right->Bracket_R;
        
        this->value = this->Left->value + this->Right->value;
            
        if (this->Left->Bracket_R && this->Right->Bracket_L && !this->Right->key && !this->Left->key)
            this->value ++;
        
    }
    
    inline void Clear ()
    {
        Left = Right = NULL;
        Bracket_L = Bracket_R = false;
        key = false;
        
        value = 0;
    }
};

S_D *Root;

#define Max 1001

class Segment_Tree_Type
{    
    private :
        
        S_D *Pool[Max];
        
        int Count;
        
        S_D* __Query_ (S_D *&now, int l, int r)
        {
            if (l <= now->l && now->r <= r)
                return now;
                
            S_D *res = Pool[++ Count];
            
            if (l <= now->Mid)
                res->Left = __Query_ (now->Left, l, r);
            if (r > now->Mid)
                res->Right = __Query_ (now->Right, l, r);
                
            if (res->Left && res->Right)
            {
                res->F_Updata (false, false, false);
                res->Up ();
            }
            else if (res->Left)
                res = res->Left;
            else if (res->Right)
                res = res->Right;
            else res = NULL;
            
            return res;
        }
        
    public :
        
        Segment_Tree_Type ()
        {
            for (int i = 0; i < Max; i ++)
                Pool[i] = new S_D ();
                
            Count = 0;
        }
        
        void Build (S_D *&now, int l, int r)
        {
            now = new S_D (l, r);
            if (l == r)
            {
                if (l == 1)
                    now->F_Updata (false, true, false);
                else if (l == N)
                    now->F_Updata (true, false, false);
                else
                    now->F_Updata (true, true, true);
                
                return ;
            }
            Build (now->Left, l, now->Mid);
            Build (now->Right, now->Mid + 1, r);
            now->Up ();
        }
        
        void Change (S_D *&now, int pos, int to)
        {
            if (now->l == now->r)
            {
                if (to == 0)
                    now->F_Updata (true, false, false);
                else if (to == 1)
                    now->F_Updata (false, true, false);
                else
                    now->F_Updata (true, true, true);
                
                return ;
            }
            if (pos <= now->Mid)
                Change (now->Left, pos, to);
            if (pos > now->Mid)
                Change (now->Right, pos, to);
            now->Up (); 
        }
    
        int Query (int x, int y)
        {
            register int now = __Query_ (Root, x, y)->value;
            
            for (int i = 1; i <= Count; i ++)
                Pool[i]->Clear ();
                
            Count = 0;
            return now;
        }
};

Segment_Tree_Type Tree;

int main (int argc, char *argv[])
{
    read (N);
    read (M);
    
    Tree.Build (Root, 1, N);     
    char type[3];
    for (int x, y; M --; )
    {
        read (x);
        read (y);
        if (x == 1)
        {
            scanf ("%s", type);
            if (type[0] == 'X')
                Tree.Change (Root, y, 2);
            else if (type[0] == '(')
                Tree.Change (Root, y, 1);
            else
                Tree.Change (Root, y, 0);
        }
        else
        {
            read (x);
            printf ("%d\n", Tree.Query (y, x));
        }
    }
    return 0;
}

 

posted @ 2017-06-18 21:52  ZlycerQan  阅读(266)  评论(0编辑  收藏  举报