• [SHOI 2015] 脑洞治疗仪


    [题目链接]

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

    [算法]

           对于操作1 , 我们首先查询区间[l0 , r0]中有多少个1 , 然后二分求出最大的x(x <= r1)使得[l1 , x]中0的个数 <= [l0 , r0]中1的个数

           对于操作2 , 对于一段区间[l , r] , 我们将它分成[l , mid]和[mid + 1 , r]两个子区间 , 那么 , 最长连续的0的个数有三种情况 :

           1. 在[l , mid]中 2. 在[mid + 1 , r]中 3. mid向前延伸最多的0的个数 + (mid + 1)向后延伸最多的0的个数

           线段树维护即可

           时间复杂度 : O(NlogN ^ 2)

    [代码]

            

    #include<bits/stdc++.h>
    using namespace std;
    #define MAXN 200010
    typedef long long ll;
    typedef long double ld;
    const int inf = 1e9;
    
    int n , m;
    
    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 , value , cnt;
            int tag;    
        } a[MAXN << 2];
        inline void build(int index , int l , int r)
        {
            a[index].l = l , a[index].r = r;
            a[index].cnt = r - l + 1;
            a[index].tag = -1;
            if (l == r) return;
            int mid = (l + r) >> 1;
            build(index << 1 , l , mid);
            build(index << 1 | 1 , mid + 1 , r);
        }
        inline void update(int x)
        {
            int l = a[x].l , r = a[x].r;
            int mid = (l + r) >> 1;
            a[x].cnt = a[x << 1].cnt + a[x << 1 | 1].cnt;
            if (a[x << 1].lm0 == mid - l + 1) a[x].lm0 = mid - l + 1 + a[x << 1 | 1].lm0;
            else a[x].lm0 = a[x << 1].lm0;
            if (a[x << 1 | 1].rm0 == r - mid) a[x].rm0 = r - mid + a[x << 1].rm0;
            else a[x].rm0 = a[x << 1 | 1].rm0;
            a[x].value = max(a[x << 1].value , a[x << 1 | 1].value);
            chkmax(a[x].value , a[x << 1].rm0 + a[x << 1 | 1].lm0);
        }
        inline void pushdown(int index)
        {
            int l = a[index].l , r = a[index].r;
            int mid = (l + r) >> 1;
            if (l == r) return;
            if (a[index].tag == 0)
            {
                a[index << 1].cnt = a[index << 1 | 1].cnt = 0;
                a[index << 1].value = mid - l + 1;
                a[index << 1 | 1].value = r - mid;
                a[index << 1].lm0 = a[index << 1].rm0 = mid - l + 1;
                a[index << 1 | 1].lm0 = a[index << 1 | 1].rm0 = r - mid;
                a[index << 1].tag = a[index << 1 | 1].tag = a[index].tag;
                a[index].tag = -1;
            }
            if (a[index].tag == 1)
            {
                a[index << 1].cnt = mid - l + 1;
                a[index << 1 | 1].cnt = r - mid;
                a[index << 1].value = a[index << 1 | 1].value = 0;
                a[index << 1].lm0 = a[index << 1].rm0 = 0;
                a[index << 1 | 1].lm0 = a[index << 1 | 1].rm0 = 0;
                a[index << 1].tag = a[index << 1 | 1].tag = a[index].tag;
                a[index].tag = -1;
            }
        }
        inline void modify(int index , int l , int r)
        {
            if (a[index].l == l && a[index].r == r)
            {
                a[index].cnt = 0;
                a[index].lm0 = a[index].rm0 = r - l + 1;
                a[index].value = r - l + 1;
                a[index].tag = 0;
                return;
            }
            pushdown(index);
            int mid = (a[index].l + a[index].r) >> 1;
            if (mid >= r) modify(index << 1 , l , r);
            else if (mid + 1 <= l) modify(index << 1 | 1 , l , r);
            else
            {
                modify(index << 1 , l , mid);
                modify(index << 1 | 1 , mid + 1 , r);
            }
            update(index);
        }
        inline int queryA(int index , int l , int r)
        {
                if (a[index].l == l && a[index].r == r)
                        return a[index].cnt;
                pushdown(index);
                int mid = (a[index].l + a[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 (a[index].l == l && a[index].r == r)
                return a[index].value;
            pushdown(index);
            int mid = (a[index].l + a[index].r) >> 1;
            if (mid >= r) return queryB(index << 1 , l , r);
            else if (mid + 1 <= l) return queryB(index << 1 | 1 , l , r);
            {
                          int ret = max(queryB(index << 1 , l , mid) , queryB(index << 1 | 1 , mid + 1 , r));
                chkmax(ret , min(mid - l + 1 , a[index << 1].rm0) + min(r - mid , a[index << 1 | 1].lm0));
                return ret;
            }
        }
        inline void change(int index , int l , int r)
        {
                if (l > r) return;
                     if (a[index].l == l && a[index].r == r)
                     {
                             a[index].cnt = r - l + 1;
                            a[index].lm0 = a[index].rm0 = a[index].value = 0;
                            a[index].tag = 1;
                            return;        
                    }
                    pushdown(index);
                    int mid = (a[index].l + a[index].r) >> 1;
                    if (mid >= r) change(index << 1 , l , r);
                    else if (mid + 1 <= l) change(index << 1 | 1 , l , r);
                    else
                    {
                            change(index << 1 , l , mid);
                            change(index << 1 | 1 , mid + 1 , r);
                    }
                    update(index);
        }
    } SGT;
    
    int main()
    {
               
        read(n); read(m);
        SGT.build(1 , 1 , n);
        for (int i = 1; i <= m; i++)
        {
            int type;
            read(type);
            if (type == 0)
            {
                int x , y;
                read(x); read(y);
                SGT.modify(1 , x , y);
            } else if (type == 1)
            {
                int l0 , r0 , l1 , r1;
                read(l0); read(r0); read(l1); read(r1);
                int cnt = SGT.queryA(1 , l0 , r0);
                SGT.modify(1 , l0 , r0);
                int l = l1 , r = r1 , loc = 0;
                while (l <= r)
                {
                        int mid = (l + r) >> 1;
                        if ((mid - l1 + 1) - SGT.queryA(1 , l1 , mid) <= cnt)
                        {
                                loc = mid;
                                l = mid + 1;
                                    } else r = mid - 1;
                            }
                SGT.change(1 , l1 , loc);
            } else
            {
                int l , r;
                read(l); read(r);
                printf("%d
    " , SGT.queryB(1 , l , r));
            }
        }
        
        return 0;
    }
  • 相关阅读:
    【BZOJ4198】[Noi2015]荷马史诗 贪心+堆
    【BZOJ4200】[Noi2015]小园丁与老司机 DP+最小流
    【BZOJ2839】集合计数 组合数+容斥
    【BZOJ2989】数列 kd-tree
    【BZOJ4240】有趣的家庭菜园 树状数组+贪心
    【BZOJ4238】电压 DFS树
    【BZOJ4237】稻草人 cdq分治+单调栈+二分
    Python Web学习笔记之WebSocket原理说明
    Python Web学习笔记之Cookie,Session,Token区别
    Python Web学习笔记之图解TCP/IP协议和浅析算法
  • 原文地址:https://www.cnblogs.com/evenbao/p/10088919.html
Copyright © 2020-2023  润新知