[SCOI 2010] 序列操作

[题目链接]

       https://www.lydsy.com/JudgeOnline/problem.php?id=1858

[算法]

        用线段树维护 :

        1. 区间中1的个数

        2. 左端点向右延伸最长连续1的长度

        3. 右端点向左延伸最长连续1的长度

        4. 左端点向右延伸最长连续0的长度

        5. 右端点向左延伸最长连续0的长度

        6. 区间中最多有多少个连续的1

        细节较为繁琐 , 写代码时要严谨

        时间复杂度 : O(NlogN)

[代码]

         

#include<bits/stdc++.h>
using namespace std;
#define MAXN 100010
typedef long long ll;
typedef long double ld;

int n , q;
int a[MAXN];

template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
template <typename T> inline void read(T &x)
{
    T f = 1; x = 0;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
    for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
    x *= f;
}
struct Segment_Tree
{
    struct Node
    {
        int l , r;
        int lm0 , rm0 , lm1 , rm1 , value0 , value1 , cnt;
        int taga , tagb;    
    } Tree[MAXN << 2];
    inline void update(int index)
    {
        int l = Tree[index].l , r = Tree[index].r;
        int mid = (l + r) >> 1;
        Tree[index].cnt = Tree[index << 1].cnt + Tree[index << 1 | 1].cnt;
        if (Tree[index << 1].cnt == mid - l + 1) Tree[index].lm1 = mid - l + 1 + Tree[index << 1 | 1].lm1;
        else Tree[index].lm1 = Tree[index << 1].lm1;
        if (Tree[index << 1 | 1].cnt == r - mid) Tree[index].rm1 = r - mid + Tree[index << 1].rm1;
        else Tree[index].rm1 = Tree[index << 1 | 1].rm1;
        if (Tree[index << 1].cnt == 0) Tree[index].lm0 = mid - l + 1 + Tree[index << 1 | 1].lm0;
        else Tree[index].lm0 = Tree[index << 1].lm0;
        if (Tree[index << 1 | 1].cnt == 0) Tree[index].rm0 = r - mid + Tree[index << 1].rm0;
        else Tree[index].rm0 = Tree[index << 1 | 1].rm0;
        Tree[index].value0 = max(Tree[index << 1].value0 , Tree[index << 1 | 1].value0);
        chkmax(Tree[index].value0 , Tree[index << 1].rm0 + Tree[index << 1 | 1].lm0);
        Tree[index].value1 = max(Tree[index << 1].value1 , Tree[index << 1 | 1].value1);
        chkmax(Tree[index].value1 , Tree[index << 1].rm1 + Tree[index << 1 | 1].lm1);
    }
    inline void pushdown(int index)
    {
        int l = Tree[index].l , r = Tree[index].r;
        int mid = (l + r) >> 1;
        if (Tree[index].taga == 0)
        {
            Tree[index << 1].cnt = Tree[index << 1 | 1].cnt = 0;
            Tree[index << 1].lm1 = Tree[index << 1 | 1].lm1 = 0;
            Tree[index << 1].rm1 = Tree[index << 1 | 1].rm1 = 0;
            Tree[index << 1].lm0 = Tree[index << 1].rm0 =  mid - l + 1;
            Tree[index << 1 | 1].lm0 = Tree[index << 1 | 1].rm0 = r - mid;
            Tree[index << 1].value0 = mid - l + 1;
            Tree[index << 1 | 1].value0 = r - mid;
            Tree[index << 1].value1 = Tree[index << 1 | 1].value1 = 0;
            Tree[index << 1].taga = Tree[index << 1 | 1].taga = 0;
            Tree[index << 1].tagb = Tree[index << 1 | 1].tagb = 0;
            Tree[index].taga = -1;
        } else if (Tree[index].taga == 1)
        {
            Tree[index << 1].cnt = mid - l + 1;
            Tree[index << 1 | 1].cnt = r - mid;
            Tree[index << 1].lm1 = Tree[index << 1].rm1 = mid - l + 1;
            Tree[index << 1].lm0 = Tree[index << 1].rm0 = 0;
            Tree[index << 1 | 1].lm0 = Tree[index << 1 | 1].rm0 = 0;
            Tree[index << 1 | 1].lm1 = Tree[index << 1 | 1].rm1 = r - mid;
            Tree[index << 1].value0 = Tree[index << 1 | 1].value0 = 0;
            Tree[index << 1].value1 = mid - l + 1;
            Tree[index << 1 | 1].value1 = r - mid;
            Tree[index << 1].taga = Tree[index << 1 | 1].taga = 1;
            Tree[index << 1].tagb = Tree[index << 1 | 1].tagb = 0;
            Tree[index].taga = -1;
        }
        if (Tree[index].tagb)
        {
            Tree[index << 1].cnt = (mid - l + 1) - Tree[index << 1].cnt;
            Tree[index << 1 | 1].cnt = (r - mid) - Tree[index << 1 | 1].cnt;
            swap(Tree[index << 1].value0 , Tree[index << 1].value1);
            swap(Tree[index << 1 | 1].value0 , Tree[index << 1 | 1].value1);
            swap(Tree[index << 1].lm0 , Tree[index << 1].lm1);
            swap(Tree[index << 1].rm0 , Tree[index << 1].rm1);
            swap(Tree[index << 1 | 1].lm0 , Tree[index << 1 | 1].lm1);
            swap(Tree[index << 1 | 1].rm0 , Tree[index << 1 | 1].rm1);
            Tree[index << 1].tagb ^= 1;
            Tree[index << 1 | 1].tagb ^= 1;
            Tree[index].tagb = 0;
        } 
    }
    inline void build(int index , int l , int r)
    {
        Tree[index].l = l; Tree[index].r = r;
        Tree[index].taga = -1;
        Tree[index].tagb = 0;
        if (l == r)
        {
            if (a[l] == 0)
            {
                Tree[index].lm0 = Tree[index].rm0 = 1;    
                Tree[index].value0 = 1;
            } else
            {
                Tree[index].lm1 = Tree[index].rm1 = 1;
                Tree[index].value1 = 1;
                Tree[index].cnt = 1;
            }
            return;
        }
        int mid = (l + r) >> 1;
        build(index << 1 , l , mid);
        build(index << 1 | 1 , mid + 1 , r);
        update(index);
    }
    inline void modify(int index , int l , int r , int value)
    {
        if (Tree[index].l == l && Tree[index].r == r)
        {
            if (value == 0)
            {
                    Tree[index].lm1 = Tree[index].rm1 = 0;
                Tree[index].lm0 = Tree[index].rm0 = r - l + 1;
                Tree[index].cnt = 0;
                Tree[index].value0 = r - l + 1;
                Tree[index].value1 = 0;
                Tree[index].taga = value;
                Tree[index].tagb = 0;
            } else
            {
                    Tree[index].lm0 = Tree[index].rm0 = 0;
                Tree[index].lm1 = Tree[index].rm1 = r - l + 1;
                Tree[index].cnt = r - l + 1;
                Tree[index].value0 = 0;
                Tree[index].value1 = r - l + 1;
                Tree[index].taga = value;
                Tree[index].tagb = 0;
            }
            return;
        }
        pushdown(index);
        int mid = (Tree[index].l + Tree[index].r) >> 1;
        if (mid >= r) modify(index << 1 , l , r , value);
        else if (mid + 1 <= l) modify(index << 1 | 1 , l , r , value);
        else
        {
            modify(index << 1 , l , mid , value);
            modify(index << 1 | 1 , mid + 1 , r , value);
        }
        update(index);
    }
    inline void reverse(int index , int l , int r)
    {
        if (Tree[index].l == l && Tree[index].r == r)
        {
            Tree[index].cnt = (r - l + 1) - Tree[index].cnt;
                        swap(Tree[index].lm0 , Tree[index].lm1);
                        swap(Tree[index].rm0 , Tree[index].rm1);
                        swap(Tree[index].value0 , Tree[index].value1);
            Tree[index].tagb ^= 1;
            return;
        }
        pushdown(index);
        int mid = (Tree[index].l + Tree[index].r) >> 1;
        if (mid >= r) reverse(index << 1 , l , r);
        else if (mid + 1 <= l) reverse(index << 1 | 1 , l , r);
        else
        {
            reverse(index << 1 , l , mid);
            reverse(index << 1 | 1 , mid + 1 , r);
        }
        update(index);
    }
    inline int queryA(int index , int l , int r)
    {
        if (Tree[index].l == l && Tree[index].r == r)
            return Tree[index].cnt;
        pushdown(index);
        int mid = (Tree[index].l + Tree[index].r) >> 1;
        if (mid >= r) return queryA(index << 1 , l , r);
        else if (mid + 1 <= l) return queryA(index << 1 | 1 , l , r);
        else return queryA(index << 1 , l , mid) + queryA(index << 1 | 1 , mid + 1 , r);
    }
    inline int queryB(int index , int l , int r)
    {
        if (Tree[index].l == l && Tree[index].r == r)
            return Tree[index].value1;
        pushdown(index);
        int mid = (Tree[index].l + Tree[index].r) >> 1;
        if (mid >= r) return queryB(index << 1 , l , r);
        else if (mid + 1 <= l) return queryB(index << 1 | 1 , l , r);
        else 
        {
            int ret = max(queryB(index << 1 , l , mid) , queryB(index << 1 | 1 , mid + 1 , r));
            chkmax(ret , min(mid - l + 1 , Tree[index << 1].rm1) + min(r - mid , Tree[index << 1 | 1].lm1));
            return ret;
        }
    }
} SGT;

int main()
{
    
    read(n); read(q);
    for (int i = 1; i <= n; i++) read(a[i]);
    SGT.build(1 , 1 , n);
    while (q--)
    {
        int type;
        read(type);
        if (type == 0)
        {
            int l , r;
            read(l); read(r);
            ++l; ++r;
            SGT.modify(1 , l , r , 0);    
        } else if (type == 1)
        {
            int l , r;
            read(l); read(r);
            ++l; ++r;
            SGT.modify(1 , l , r , 1);
        } else if (type == 2)
        {
            int l , r;
            read(l); read(r);
            ++l; ++r;
            SGT.reverse(1 , l , r);
        } else if (type == 3)
        {
            int l , r;
            read(l); read(r);
            ++l; ++r;
            printf("%d
" , SGT.queryA(1 , l , r));
        } else
        {
            int l , r;
            read(l); read(r);
            ++l; ++r;
            printf("%d
" , SGT.queryB(1 , l , r));
        }
    }
    
    return 0;
}
原文地址:https://www.cnblogs.com/evenbao/p/10051044.html