作者: 霄汉的蛋
重新开端时期: 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;
    }

发表评论

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