(WAWAWAWAWAWA) BZOJ 1858: [Scoi2010]序列操作

二次联通门 : BZOJ 1858: [Scoi2010]序列操作

 

 

 

 

/*
  BZOJ 1858: [Scoi2010]序列操作
    已经...
    没有什么好怕的的了...

    16K的代码...

    调个MMP啊...

*/
#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 ();
    }
}

inline int max (int a, int b)
{
    return a > b ? a : b;
}

inline int min (int a, int b)
{
    return a < b ? a : b;
}

inline int swap (int &a, int &b)
{
    register int now = a;
    a = b;
    b = now;
}

struct Segment_Tree_Data
{
    Segment_Tree_Data *Left, *Right;
    
    int Mid;
    int key;
    
    int l, r;
    
    int Nor_Flandre;
    bool Rev_Flandre;
    
    int Zero_Prefix_, Zero_Suffix_;
    int Zero_Series_Count;
    int Zero_Count;
    
    int One_Prefix_, One_Suffix_;
    int One_Series_Count;
    int One_Count;
    
    Segment_Tree_Data ()
    {
        Left = Right = NULL;
        Nor_Flandre = 0;
        Rev_Flandre = 0;
    }
    
    
    inline void Clear_One ()
    {
        One_Count = 0;
        One_Prefix_ = One_Suffix_ = 0;
        One_Series_Count = 0;
    }
    
    inline void Clear_Zero ()
    {
        Zero_Count = 0;
        Zero_Prefix_ = Zero_Suffix_ = 0;
        Zero_Series_Count = 0;
    }
    
    inline void Cover_One ()
    {
        One_Count = r - l + 1;
        One_Prefix_ = One_Count;
        One_Suffix_ = One_Count;
        One_Series_Count = One_Count;
    }
    
    inline void Cover_Zero ()
    {
        Zero_Count = r - l + 1;
        Zero_Prefix_ = Zero_Count;
        Zero_Suffix_ = Zero_Count;
        Zero_Series_Count = Zero_Count;
    }
    
    inline void Swap_Zero_and_One ()
    {
        swap (Zero_Count, One_Count);
        swap (Zero_Prefix_, One_Prefix_);
        swap (Zero_Suffix_, One_Suffix_);
        swap (Zero_Series_Count, One_Series_Count);
    }
};

Segment_Tree_Data *Root;

int Answer;

struct Answer_Type
{
    int size;
    int _Prefix, _Suffix;
    int Count;
    int Answer;
};

class Segment_Tree_Type
{
    private :
        
        inline void Up (Segment_Tree_Data *&now)
        {
            if (now->l == now->r)
                return ;/*
            now->Zero_Prefix_ = max (now->Left->Zero_Prefix_, now-

>Left->Zero_Count + now->Right->Zero_Prefix_);
            now->Zero_Suffix_ = max (now->Right->Zero_Suffix_, now-

>Right->Zero_Count + now->Left->Zero_Suffix_);
            now->Zero_Series_Count = max (max (now->Left-

>Zero_Series_Count, now->Right->Zero_Series_Count), now->Right-

>Zero_Prefix_ + now->Left->Zero_Suffix_);
            
            now->One_Prefix_ = max (now->Left->One_Prefix_, now->Left-

>One_Count + now->Right->One_Prefix_);
            now->One_Suffix_ = max (now->Right->One_Suffix_, now-

>Right->One_Count + now->Left->One_Suffix_);
            now->One_Series_Count = max (max (now->Left-

>One_Series_Count, now->Right->One_Series_Count), now->Right-

>One_Prefix_ + now->Left->One_Suffix_); 
            */
            now->One_Prefix_ = now->Left->One_Count == now

->Left->r - now->Left->l + 1 ? now->Left->One_Count : now->Left-

>One_Prefix_;
            now->One_Suffix_ = now->Right->One_Count == 

now->Right->r - now->Right->l + 1 ? now->Right->One_Count : now->Right

->One_Suffix_;
    
            now->Zero_Prefix_ = now->Left->Zero_Count == 

now->Left->r - now->Left->l + 1 ? now->Left->Zero_Count : now->Left-

>Zero_Prefix_;
            now->Zero_Suffix_ = now->Right->Zero_Count == 

now->Right->r - now->Right->l + 1 ? now->Right->Zero_Count : now-

>Right->Zero_Suffix_;

            now->One_Series_Count = max (max (now->Left-

>One_Series_Count, now->Right->One_Series_Count), now->Left-

>One_Suffix_ + now->Right->One_Prefix_);
            now->Zero_Series_Count = max (max (now->Left-

>Zero_Series_Count, now->Right->Zero_Series_Count), now->Left-

>Zero_Suffix_ + now->Right->Zero_Prefix_);
            
            now->One_Count = now->Left->One_Count + now->Right-

>One_Count;
            now->Zero_Count = now->Left->Zero_Count + now->Right-

>Zero_Count;
            return ;
        }
    
        inline void Down (Segment_Tree_Data *&now)
        {
            if (now->l == now->r)
                return ;
            if (now->Nor_Flandre)
            {
                if (now->Nor_Flandre == 1)            
                {/*
                    now->Left->One_Count = now->Left->r - now->Left->l 

+ 1;
                    now->Right->One_Count = now->Right->r - now->Right

->l + 1;
                    
                    now->Left->One_Prefix_ = now->Left->One_Count;
                    now->Left->One_Suffix_ = now->Left->One_Count;
                    now->Right->One_Prefix_ = now->Right->One_Count;
                    now->Right->One_Suffix_ = now->Right->One_Count;
                    
                    now->Left->One_Series_Count = now->Left->One_Count;
                    now->Right->One_Series_Count = now->Right-

>One_Count;
                    
                    now->Left->Nor_Flandre = 1;
                    now->Right->Nor_Flandre = 1;
                    */
                    now->Left->Cover_One ();
                    now->Right->Cover_One (); 
                    now->Left->Rev_Flandre = false;
                    now->Right->Rev_Flandre = false;
                    now->Left->Clear_Zero ();
                    now->Right->Clear_Zero ();
                     
                    now->Nor_Flandre = 0;
                }
                else if (now->Nor_Flandre == 2)              
                {/*
                    now->Left->Zero_Count = now->Left->r - now->Left->l 

+ 1;
                    now->Right->Zero_Count = now->Right->r - now-

>Right->l + 1;
                    
                    now->Left->Zero_Prefix_ = now->Left->Zero_Count;
                    now->Left->Zero_Suffix_ = now->Left->Zero_Count;
                    now->Right->Zero_Prefix_ = now->Right->Zero_Count;
                    now->Right->Zero_Suffix_ = now->Right->Zero_Count;
                    
                    now->Left->Zero_Series_Count = now->Left-

>Zero_Count;
                    now->Right->Zero_Series_Count = now->Right-

>Zero_Count;
                    
                    now->Left->Nor_Flandre = 2;
                    now->Right->Nor_Flandre = 2;
                    */
                    now->Left->Cover_Zero ();
                    now->Right->Cover_Zero (); 
                    now->Left->Rev_Flandre = false;
                    now->Right->Rev_Flandre = false;
                    now->Left->Clear_One ();
                    now->Right->Clear_One ();
                    
                    now->Nor_Flandre = 0;
                }
            }
            if (now->Rev_Flandre)
            {/*
                swap (now->Left->One_Count, now->Left->Zero_Count);
                swap (now->Left->One_Prefix_, now->Left->Zero_Count);
                swap (now->Left->One_Series_Count, now->Left-

>Zero_Series_Count);
                swap (now->Left->One_Suffix_, now->Left->Zero_Suffix_);
                
                swap (now->Right->One_Count, now->Right->Zero_Count);
                swap (now->Right->One_Prefix_, now->Right->Zero_Count);
                swap (now->Right->One_Series_Count, now->Right-

>Zero_Series_Count);
                swap (now->Right->One_Suffix_, now->Left-

>Zero_Suffix_);
               */
                   now->Left->Swap_Zero_and_One ();
                now->Right->Swap_Zero_and_One ();  
                now->Left->Rev_Flandre = true;
                now->Right->Rev_Flandre = true;
                
                now->Rev_Flandre = false;
            }
        }
        
    public :
        
        void Build (Segment_Tree_Data *&now, int l, int r)
        {
            now = new Segment_Tree_Data;
            now->l = l;
            now->r = r;
            if (l == r)
            {
                read (now->key);
                if (now->key)
                {
                    now->One_Count = 1;
                    now->One_Prefix_ = 1;
                    now->One_Suffix_ = 1;
                    now->One_Series_Count = 1;
                    now->Clear_Zero (); 
                    return ;
                }
                else
                {
                    now->Zero_Count = 1;
                    now->Zero_Prefix_ = 1;
                    now->Zero_Suffix_ = 1;
                    now->Zero_Series_Count = 1;
                    now->Clear_One ();
                    return ;
                }
            }
            now->Mid = l + r >> 1;
            Build (now->Left, l, now->Mid);
            Build (now->Right, now->Mid + 1, r);
            Up (now);
        }
        
        
        void Change_First (Segment_Tree_Data *&now, int l, int r)
        {
            if (l <= now->l && now->r <= r)
            {/*
                now->Zero_Count = now->r - now->l + 1;
                now->Zero_Prefix_ = now->Zero_Count;
                now->Zero_Suffix_ = now->Zero_Count;
                now->Zero_Series_Count = now->Zero_Count;
*/
                now->Cover_Zero (); 
                now->Clear_One (); 
                now->Nor_Flandre = 2;
                return ;
            }
            Down (now);
            if (l <= now->Mid)
                Change_First (now->Left, l, min (now->Mid, r));
            if (r > now->Mid)
                Change_First (now->Right, max (now->Mid + 1, l), r);
            Up (now);
        }
        
        void Change_Second (Segment_Tree_Data *&now, int l, int r)
        {
            if (l <= now->l && now->r <= r)
            {
                now->Cover_One ();
                now->Clear_Zero ();
                
                now->Nor_Flandre = 1;
                return ;
            }
            Down (now);
            if (l <= now->Mid)
                Change_Second (now->Left, l, min (now->Mid, r));
            if (r > now->Mid)
                Change_Second (now->Right, max (now->Mid + 1, l), r);
            Up (now);
        }
        
        void Change_Third (Segment_Tree_Data *&now, int l, int r)
        {
            if (l <= now->l && now->r <= r)
            {
                now->Swap_Zero_and_One ();
                now->Rev_Flandre = true;
                return ; 
            }
            Down (now);
            if (l <= now->Mid)
                Change_Third (now->Left, l, min (now->Mid, r));
            if (r > now->Mid)
                Change_Third (now->Right, max (now->Mid + 1, l), r);
            Up (now);
        }
        
        int Query_First (Segment_Tree_Data *&now, int l, int r)
        {
            if (l <= now->l && now->r <= r)
                return now->One_Count;
            Down (now);
            register int res = 0;
            if (l <= now->Mid)
                res += Query_First (now->Left, l, min (now->Mid, r));
            if (r > now->Mid)
                res += Query_First (now->Right, max (now->Mid + 1, l), 

r);
            Up (now);
            return res;
        }
        /*
        Segment_Tree_Data *Query_Second (Segment_Tree_Data *&now, int 

l, int r)
        {
            if (l <= now->l && now->r <= r)
                return now;
            Down (now);
            Up (now);
            Segment_Tree_Data *res = new Segment_Tree_Data;
            Segment_Tree_Data *now_1 = new Segment_Tree_Data, *now_2 = 

new Segment_Tree_Data;
            bool flag_1 = false, flag_2 = false;
            if (l <= now->Mid)
            {
                flag_1 = true;
                now_1 = Query_Second (now->Left, l, min (now->Mid, r));
            }
            if (r > now->Mid)
            {
                flag_2 = true;
                now_2 = Query_Second (now->Right, max (now->Mid + 1, 

l), r);
            }
            if (flag_1 && flag_2)
            {   
                now_1 = Query_Second (now->Left, l, min (now->Mid, r));
                now_2 = Query_Second (now->Right, max (now->Mid + 1, 

l), r);
                res.One_Prefix_ = max (now_1.One_Prefix_, 

now_1.One_Count + now_2.One_Prefix_);
                res.One_Suffix_ = max (now_2.One_Suffix_, 

now_2.One_Count + now_1.One_Suffix_);
                res.One_Series_Count = max (max 

(now_1.One_Series_Count, now_2.One_Series_Count), now_1.One_Suffix_ + 

now_2.One_Prefix_);
                return res;
                
              now_1 = Query_Second (now->Left, l, min (now->Mid, r));
              now_2 = Query_Second (now->Right, max (now->Mid + 1, l), 

r);
                res->One_Count = now_1->One_Count + 

now_2->One_Count;
                res->One_Prefix_ = max (now_1->One_Prefix_, now_1-

>One_Count + now_2->One_Prefix_);
                res->One_Suffix_ = max (now_2->One_Suffix_, now_2-

>One_Count + now_1->One_Suffix_);
                res->One_Series_Count = max (max (now_1-

>One_Series_Count, now_2->One_Series_Count), now_1->One_Suffix_ + 

now_2->One_Prefix_);
                Answer = max (Answer, res->One_Series_Count);
                Answer = max (Answer, res->One_Prefix_);
                Answer = max (Answer, res->One_Suffix_);
                return res;
            }
            if (flag_1)
            {
                Answer = max (Answer, now_1->One_Series_Count);
                Answer = max (Answer, now_1->One_Prefix_);
                Answer = max (Answer, now_1->One_Suffix_);
                return now_1;
            }
            if (flag_2)
            {
                Answer = max (Answer, now_2-

>One_Series_Count);
                Answer = max (Answer, now_2-

>One_Prefix_);
                Answer = max (Answer, now_2-

>One_Suffix_);
                return now_2;
            }
        }*/
        
        
        Answer_Type Query_ (Segment_Tree_Data *&now, int l, int r)
        {
            if (l <= now->l && now->r <= r)
                return (Answer_Type) 
                {
                    now->r - now->l + 1,
                    now->One_Prefix_,
                    now->One_Suffix_,
                    now->One_Count,
                    now->One_Series_Count    
                };
            Down (now);
            Up (now);
            Answer_Type now_1, now_2;
            register bool flag_1 = false, flag_2 = false;
            if (l <= now->Mid)
            {
                flag_1 = true;
                now_1 = Query_ (now->Left, l, min (now

->Mid, r));
            }
            if (r > now->Mid)
            {
                flag_2 = true;
                now_2 = Query_ (now->Right, max (now-

>Mid + 1, l), r);
            }
            if (flag_1 && flag_2)
            {
                Answer_Type res;
                res.Count = now_1.Count + now_2.Count;
                res._Prefix = now_1.size == now_1.Count 

? now_1.Count : now_1._Prefix;
                res._Suffix = now_2.size == now_2.Count 

? now_2.Count : now_2._Suffix;
                res.Answer = max (max (now_1.Answer, 

now_2.Answer), now_1._Suffix + now_2._Prefix);
                return res;
            }
            return flag_1 ? now_1 : now_2;
        }
};

Segment_Tree_Type Tree;
int N, M;

int main (int argc, char *argv[])
{
    read (N);
    read (M);
    Root = NULL;
    Tree.Build (Root, 1, N); 
    int type, x, y;
    for (; M--; )
    {
        read (type);
        read (x);
        x++;
        read (y);
        y++;
        if (type == 0)
            Tree.Change_First (Root, x, y);
        else if (type == 1)
            Tree.Change_Second (Root, x, y);
        else if (type == 2)
            Tree.Change_Third (Root, x, y);
        else if (type == 3)
           printf ("%d\n", Tree.Query_First (Root, x, y)); 
        else
        {
//            Answer = -1;
//            Tree.Query_Second (Root, x, y);
//            printf ("%d\n", Answer);
            Answer_Type res = Tree.Query_ (Root, x, y); 
            printf ("%d\n", max (max (res._Prefix, 

res._Suffix), res.Answer));
        }
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/ZlycerQan/p/6940745.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值