作者: 碧落的蛋
使现代化工夫: 2018-10-20 23:42
在TA的视频博客上检查  18 


因此成绩解答相当长的时间了, 因此成绩很难整理, 看一眼因此成绩的处置即使能帮忙你们专卖的

$debug$ 了任何人后部, 笔者霉臭当心什么?

从视频博客中变化, 我以为认识体式即使会尖响。。

率先,我会解说, 行树因此东西, 每人的笔迹都相异点, 处置成绩的次要企图是看我的思绪即使

男教师成绩得另外的名, 对段树有大好的领会

(从后面追求赞扬

金币珍藏的集合的 XD

序文

此处置方案将集合在以下成绩上,以使, 不认识可以是私人的使订婚黑金色、黑色Q, 有工夫答复

  1. 总体思绪和维持基本原理
  2. 俯卧撑(两人都谈过, 倘若你完全不懂,你可能会指出
  3. 注意讲 $pushdown$ 不活动标记举动 明亮的的处置

很多得 $10$ 团体达到目标每人都无意记下细目,并且在买卖中不恰当。

固然, 在因此成绩解答领先请看一下为本身设想, 你可以受到很多。

低声说的话, 因此成绩有弘量的信号。 倘若有口误请告诉我。 谢谢你

笔者开端吧。

对本身 & $RNG$ : 傲卒多降
LPL$加油!

P2572 [Scoi2010]序列举动

标题问题刻画
LXHGW近的收到了分支01续集,序列包罗n标号字,这些数字指责零,或许1,现时有五个的替换和查询举动用是故序列:

0 a b [答], b]轮流达到目标自己人数字都变为zer

1 a b [答], b]轮流达到目标自己人数字变为

2 a b [答],b]轮流达到目标自己人数字都是反向的。,更确切地说,自己人的0都做1,将自己人1替换为0

3 a b 讯问, B]衣服的胸襟有足个1

4 a b 讯问, b]至多有两三个陆续的1次

因为每个查询举动,LXHGW必要答复,油腔滑调的的顺序员,你能帮他吗?


口误日记: 质地较多且要紧, 它将用粗体写在上面


Solution

分割树, 必要维持以下知识:

  1. $sum$ 区间 $1$ 的标号
  2. $max[0/1]$ 区间内 $0/1$ 如同比实际时间长的陆续子段
  3. $lmax[0/1]$ 包罗Interva如同比实际时间长的的左晚期的 $0/1$ 子段
  4. $rmax[0/1]$ 包罗Interva如同比实际时间长的的右晚期的 $0/1$ 子段

认真说空的空间或地点举动, 还必要两个副打手势:

  1. $lazy = {-1, 0, 1}$ 为 $-1$ 代表无国籍的, 为 $0/1$ 表现轮流的自己人分派 $0/1$

有很多的元素必要维持, 先讲 $pushup$
区间和直接地增加的人或事物
包罗左晚期的的陆续子段有两种命运:

  1. 左Interva的直接地争吵 $lmax$
  2. 当左轮流满时 / 全期, 左晚期的可以穿插, 添加越位的Interva的相称

立刻轮流使现代化支持

因为Interva的如同比实际时间长的陆续爆炸, 有三种命运

  1. 左Interva的直接地争吵较大值
  2. 右Interva中较大值的直接地争吵
  3. 右晚期的左轮流的如同比实际时间长的爆炸 + 右轮流包罗左晚期的的如同比实际时间长的子段, 更确切地说,如同比实际时间长的的相称投诚区间分开

关于几点是贫穷的 $0/1$ 议论, 顺序达到目标直接地两层圈子


过后是费心。 $pushdown$

感到后悔的是,我,任何人必要冲进省队的球员,缺席

在分割树 $pushdown$ 举动中, 笔者必要弄清几件事:

  1. 标记的优先思索的事

2. 砍掉标记即使会冲撞子杂种的上的以此类推典型标记?

在喂,笔者关怀另外的点(第若干是, 因而轮流分派标记霉臭先被反缀编, 拆标记时必要将翻转标记清空)

装配副打手势时, 笔者不光必要显式地将因此标记放到子杂种的上, 恒等的典型的标记霉臭若何机会, 霉臭明亮的地揭晓,因此标记的反缀编将冲撞 不恒等的典型的标记冲撞是什么?

不隐瞒的歧视相等的数量典型的冲撞通常缺席成绩, 倘若轮流标记为Dow, 子杂种的的轮流相加副打手势将此值相加。

以因此动机的为例:

下决定轮流分派标记时, 子轮流分派标记不光必要使现代化到此VAL, 您还必要通便子杂种的翻转TA(但这如同缺席什么印象。, 下决定分派标记时,翻转标记将被清空。

当轮流翻转标记被拆开时, 必要分两种命运思索此标记下推对子区间 分派标记 和 翻转标记的印象

认真说分派标记的优先思索的事大于翻转标记, 在有分派标记的命运下, 直接地翻转分派标记

在以此类推命运下,加速标记xor接近


其余的见信号 话虽这样的说工夫很长,但它是对线路段Tre的深入懂得。

这样的完善地认真说自己人命运 $OI$ 爱好运动的人基本素质


好吧,就这样的。, $RNG$ 别心灰意冷, 你是最好的。; $S8$ ,$lpl$ 加油!

Code

#include
#include
#include
#include
#include
#include
#define LL long long
#define 代表(一), x, y) 因为(int i = (x);i <= (y);i++)
using namespace std;
int RD(){
    int out = 0,flag = 1;char c = getchar();
    当(c < ''0'' || c >''9''){if(c == -)打手势 = -1;c = getchar();}
    当(c >= ''0'' && c <= ''9''){out = out * 10 + c - ''0'';c = getchar();}
    return flag * out;
    }
const int maxn = 200019;
int num, na;
int v[maxn];
#define lid (id << 1)
#define rid (id << 1) | 1
//int max(int a, int b){return a > b ? a : B;//口授快?
struct seg_tree{
    int l, r;
    int sum;
    int lazy;//-1.NULL  整个0。  1.全为1
    int rev;
    int 帽舌[2], l帽舌[2], r帽舌[2];
    }tree[maxn << 2];
void pushup(int ID)
    树[id].sum = 树[lid].sum + 树[rid].sum;
    代表(一), 0, 1){
        树[id].lmax[i] = 树[盖].lmax[i];
        倘若(i == 1 && 树[lid].sum == 树[lid].r - 树[盖].l + 1)//左轮流满
            树[id].lmax[i] += 树[rid].lmax[我];/可以遮断
        else 倘若(i == 0 && 树[lid].sum == 0)//左轮流为空
            树[id].lmax[i] += 树[rid].lmax[i];

        树[id].rmax[i] = 树[RID].rmax[i];
        倘若(i == 1 && 树[rid].sum == 树[RID].r - 树[rid].l + 1)
            树[id].rmax[i] += 树[lid].rmax[i];
        else 倘若(i == 0 && 树[rid].sum == 0)
            树[id].rmax[i] += 树[lid].rmax[i];

        tree[id].max[i] = 树[lid].rmax[i] + 树[rid].lmax[一];/调解:充当调解人
        tree[id].max[i] = max(tree[id].max[i], tree[lid].max[I];//争吵Subinterva
        tree[id].max[i] = max(tree[id].max[i], tree[rid].max[i]);
        }
    }
void build(int id, int l, int r){
    树[id].l = l, 树[id].r = r, 树[ID].无根据的 = -1;
    if(l == r){
        树[id].sum = v[l];
        tree[id].max[0] = 树[id].lmax[0] = 树[id].rmax[0] = v[l] == 0;
        tree[id].max[1] = 树[id].lmax[1] = 树[id].rmax[1] = v[l] == 1;
        return ;
        }
    int mid = (l + r) >> 1;
    创造(盖, l, 中), 排列(RID, mid + 1, r);
    俯卧撑(ID)
    }
void 下推(int ID)
    if(树[id].lazy != 1)//优先思索的事极好的
        树[ID].rev = 0;//通便标记
        int val = 树[ID].无根据的
        树[lid].sum = (树[lid].r - 树[盖].l + 1) * val;
        树[rid].sum = (树[RID].r - 树[rid].l + 1) * val;

        树[盖].lazy = 树[rid].lazy = val;
        树[lid].rev = 树[RID].rev = 0;

        树[lid].最大[val] 
        = 树[盖].lmax[val] 
        = 树[lid].rmax[val] 
        = 树[lid].r - 树[盖].l + 1;
        树[lid].最大[val ^ 1] 
        = 树[盖].lmax[val ^ 1] 
        = 树[lid].rmax[val ^ 1] 
        = 0;

        树[RID].最大[VAL] 
        = 树[rid].lmax[val] 
        = 树[rid].rmax[val] 
        = 树[RID].r - 树[rid].l + 1;
        树[RID].最大[VAL ^ 1] 
        = 树[rid].lmax[val ^ 1] 
        = 树[RID].rmax[val ^ 1] 
        = 0;

        树[ID].无根据的 = -1;
        }
    if(树[ID].rev){
        树[lid].sum = (树[lid].r - 树[盖].l + 1) - 树[lid].sum;
        树[rid].sum = (树[RID].r - 树[rid].l + 1) - 树[rid].sum;

        if(树[盖].lazy != -1)树[盖].lazy ^= 1;//思索优先思索的事, 对以此类推标记的冲撞
        else 树[lid].rev ^= 1;
        if(树[rid].lazy != -1)树[rid].lazy ^= 1;
        else 树[RID].rev ^= 1;

        互换(树[lid].max[0], 树[lid].帽舌[1]
        swap(树[盖].lmax[0], 树[盖].lmax[1]);
        swap(树[lid].rmax[0], 树[lid].rmax[1]);

        互换(树[RID].帽舌[0], 树[RID].帽舌[1]
        swap(树[rid].lmax[0], 树[rid].lmax[1]);
        swap(树[RID].rmax[0], 树[RID].rmax[1]);

        树[ID].rev = 0;
        }
    }
void 使现代化(int id, int val, int l, int r){
    下推(ID)
    if(树[id].l == l && 树[id].r == r){
        倘若(VAL == 0 || val == 1){
            树[id].sum = (树[id].r - 树[id].l + 1) * val;
            树[ID].无根据的 = val;
            树[id].最大[val] 
            = 树[id].lmax[val] 
            = 树[id].rmax[val] 
            = 树[id].r - 树[id].l + 1;
            树[ID].最大[VAL ^ 1] 
            = 树[id].lmax[val ^ 1] 
            = 树[id].rmax[val ^ 1] 
            = 0;
            }
        else 倘若(VAL == 2){
            树[id].sum = (树[id].r - 树[id].l + 1) - 树[id].sum;
            树[ID].rev ^= 1;
            互换(树[ID].帽舌[0], 树[ID].帽舌[1]
            swap(树[id].lmax[0], 树[id].lmax[1]);
            swap(树[id].rmax[0], 树[id].rmax[1]);
            }
        return ;
        }
    int mid = (树[id].l + 树[id].r) >> 1;
    倘若(衣服的胸襟 < l)使现代化(RID, val, l, r);
    else 倘若(衣服的胸襟 >= r)使现代化(LID, val, l, r);
    else 使现代化(LID, val, l, 中), 使现代化(RID, val, mid + 1, r);
    俯卧撑(ID)
    }
int 查询(int id, int l, int r){
    下推(ID)
    if(树[id].l == l && 树[id].r == r)赢利 树[id].sum;
    int mid = (树[id].l + 树[id].r) >> 1;
    倘若(衣服的胸襟 < l)return 查询(RID, l, r);
    else 倘若(衣服的胸襟 >= r)赢利 查询(LID, l, r);
    else return 查询(LID, l, 中) + 查询(RID, mid + 1, r);
    }
seg_tree Q_max(int id, int l, int r){
    下推(ID)
    if(树[id].l == l && 树[id].r == r)赢利 树[ID]
    int mid = (树[id].l + 树[id].r) >> 1;
    倘若(衣服的胸襟 < l)return Q_max(rid, l, r);
    else 倘若(衣服的胸襟 >= r)赢利 Q_max(lid, l, r);
    else{
        seg_tree ret, L = Q_max(lid, l, 中), R = Q_max(rid, mid + 1, r);
        ret.sum = L.sum + R.sum;
        代表(一), 0, 1){
            [i] = [i];
            倘若(i == 1 && L.sum == L.r - L.l + 1)//左轮流满
                [i] += [我];/可以遮断
            else 倘若(i == 0 && L.sum == 0)//左轮流为空
                [i] += [i];

            [i] = [i];
            倘若(i == 1 && R.sum == R.r - R.l + 1)
                [i] += [i];
            else 倘若(i == 0 && R.sum == 0)
                [i] += [i];

            [i] = [i] + [一];/调解:充当调解人
            [i] = 帽舌([i], [I];//争吵Subinterva
            [i] = 帽舌([i], [i]);
            }
        return ret;
        }
    }
int main(){
    num = RD(), na = RD();
    代表(一), 1, num)v[i] = RD();
    排列(1, 1, 数字)
    当(不适宜
        int cmd = RD(), l = RD(), r = rd();l, r++;
        倘若(命令 == 0)update(1, 0, l, r);
        else 倘若(命令 == 1)update(1, 1, l, r);
        else 倘若(命令 == 2)update(1, 2, l, r);
        else 倘若(命令 == 3)printf(%d\n, 查询(1, l, r));
        else printf("%d\n", Q_max(1, l, r).max[1]);
        }
    return 0;
    }

发表评论

电子邮件地址不会被公开。 必填项已用*标注