BZOJ 1858: [Scoi2010]序列操作 线段树

来源:互联网 发布:知乎 english in use 编辑:程序博客网 时间:2024/05/18 00:58

Time Limit: 10 Sec Memory Limit: 64 MB
Submit: 2944 Solved: 1424

Description

lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作: 0 a b 把[a, b]区间内的所有数全变成0 1 a b 把[a, b]区间内的所有数全变成1 2 a b 把[a,b]区间内的所有数全部取反,也就是说把所有的0变成1,把所有的1变成0 3 a b 询问[a, b]区间内总共有多少个1 4 a b 询问[a, b]区间内最多有多少个连续的1 对于每一种询问操作,lxhgww都需要给出回答,聪明的程序员们,你们能帮助他吗?

Input

输入数据第一行包括2个数,n和m,分别表示序列的长度和操作数目 第二行包括n个数,表示序列的初始状态 接下来m行,每行3个数,op, a, b,(0 < = op < = 4,0 < = a < = b)

Output

对于每一个询问操作,输出一行,包括1个数,表示其对应的答案

Sample Input

10 10

0 0 0 1 1 0 1 0 1 1

1 0 2

3 0 5

2 2 2

4 0 4

0 3 6

2 3 7

4 2 8

1 0 5

0 5 6

3 3 9

Sample Output

5

2

6

5

HINT

对于30%的数据,1<=n, m<=1000 对于100%的数据,1< = n, m < = 100000

Source

Day2


感谢ZBWdalao

zbwdalao帮了我好多啊233,另外打算NOIP之前学一下gdb

如果有谁需要当年比赛的标程或者数据的,可以联系我的邮箱

这题好毒啊好毒啊好毒啊!!!以为是道水题(虽然的确是,只是我太菜),拿着就开始写,结果结果错了好久,整个下午啊233333333,从2点到现在7点48。
不过还是好开心啊,终于A了,因为和出题人的代码拍过了,交题库的时候自信打开bilibili放了一个很潇洒的BGM233


发现黄学长貌似也在这道题上卡了好久,心理平衡~

就是几个操作,只是维护的东西有点多,但其实也不是很复杂,代码写的不好看,写了160多行

要注意以下几个问题:
第一个问题,如果query需要返回结构体的,左右结构体一定要赋初始值,也即要写构造函数
第二个问题,所有的modify函数都不应该在这一层将标记消去,而是进入使用pushdown操作,(我就是在L<=l&&R>=r之后就把一个标记处理了,导致错误),所有的标记都表示下一层的操作,已经和这一层没有关系了
第三个问题,以后如果有重复的代码,直接复制的话,一定要改好,比如tree[rt<<1]复制之后某些是应该改成tree[rt<<1|1]的


#include <cstdio>#include <cstring>#include <iostream>using namespace std;const int MAXN = 200005;int a[MAXN], n, m;struct Tree{     int sum, m1, m0, l1, l0, r1, r0, mark, tag, len;     Tree() { sum = m1 = m0 = l1 = l0 = r1 = r0 = tag = len = 0; mark = -1; }    }tree[ MAXN * 4 ];void pushup( int l, int r, int rt ) {    int mid = ( l + r ) >> 1;    tree[rt].sum = tree[ rt << 1 ].sum + tree[ rt << 1 | 1 ].sum;    tree[rt].m1 = max( tree[ rt << 1 ].m1, tree[ rt << 1 | 1 ].m1 );    tree[rt].m1 = max( tree[rt].m1, tree[ rt << 1 ].r1 + tree[ rt << 1 | 1 ].l1 );    tree[rt].m0 = max( tree[ rt << 1 ].m0, tree[ rt << 1 | 1 ].m0 );    tree[rt].m0 = max( tree[rt].m0, tree[ rt << 1 ].r0 + tree[ rt << 1 | 1 ].l0 );    if( tree[ rt << 1 ].l1 == ( mid - l + 1 ) ) tree[rt].l1 =  ( mid - l + 1 ) + tree[ rt << 1 | 1 ].l1;    else                                        tree[rt].l1 = tree[ rt << 1 ].l1;    if( tree[ rt << 1 | 1 ].r1 == ( r - mid ) ) tree[rt].r1 = ( r - mid ) + tree[ rt << 1 ].r1;    else                                        tree[rt].r1 = tree[ rt << 1 | 1 ].r1;    if( tree[ rt << 1 ].l0 == ( mid - l + 1 ) ) tree[rt].l0 = ( mid - l + 1 ) + tree[ rt << 1 | 1 ].l0;    else                                        tree[rt].l0 = tree[ rt << 1 ].l0;       if( tree[ rt << 1 | 1 ].r0 == ( r - mid ) ) tree[rt].r0 = ( r - mid ) + tree[ rt << 1 ].r0;    else                                        tree[rt].r0 = tree[ rt << 1 | 1 ].r0;   }void pushdown( int l, int r, int rt ) {    int mid = ( l + r ) >> 1;    if( tree[rt].mark != -1 ) {        tree[ rt << 1 ].mark = tree[ rt << 1 | 1 ].mark = tree[rt].mark;        tree[ rt << 1 ].tag = tree[ rt << 1 | 1 ].tag = 0;        if( tree[rt].mark == 0 ) {            tree[ rt << 1 ].sum = tree[ rt << 1 | 1 ].sum = 0;            tree[ rt << 1 ].m1 = tree[ rt << 1 | 1 ].m1 = 0;            tree[ rt << 1 ].m0 = ( mid - l + 1 );             tree[ rt << 1 | 1 ].m0 = ( r - mid );            tree[ rt << 1 ].l0 = tree[ rt << 1 ].r0 = ( mid - l + 1 );            tree[ rt << 1 | 1 ].l0 = tree[ rt << 1 | 1 ].r0 = ( r - mid );            tree[ rt << 1 ].l1 = tree[ rt << 1 ].r1 = tree[ rt << 1 | 1 ].l1 = tree[ rt << 1 | 1 ].r1 = 0;        } else {            tree[ rt << 1 ].sum = ( mid - l + 1 );              tree[ rt << 1 | 1 ].sum = ( r - mid );            tree[ rt << 1 ].m1 = ( mid - l + 1 );            tree[ rt << 1 | 1 ].m1 = ( r - mid );            tree[ rt << 1 ].m0 = tree[ rt << 1 | 1 ].m0 = 0;            tree[ rt << 1 ].l0 = tree[ rt << 1 | 1 ].l0 = tree[ rt << 1 ].r0 = tree[ rt << 1 | 1 ].r0 = 0;            tree[ rt << 1 ].l1 = tree[ rt << 1 ].r1 = ( mid - l + 1 );            tree[ rt << 1 | 1 ].l1 = tree[ rt << 1 | 1 ].r1 = ( r - mid );        }        tree[rt].mark = -1;    }    if( tree[rt].tag == 1 ) {        tree[ rt << 1 ].tag ^= 1;        tree[ rt << 1 | 1 ].tag ^= 1;        tree[ rt << 1 ].sum = ( mid - l + 1 ) - tree[ rt << 1 ].sum;        tree[ rt << 1 | 1 ].sum = ( r - mid ) - tree[ rt << 1 | 1 ].sum;         swap( tree[ rt << 1 ].m1, tree[ rt << 1 ].m0 );        swap( tree[ rt << 1 ].l0, tree[ rt << 1 ].l1 );        swap( tree[ rt << 1 ].r0, tree[ rt << 1 ].r1 );        swap( tree[ rt << 1 | 1 ].m1, tree[ rt << 1 | 1 ].m0 );        swap( tree[ rt << 1 | 1 ].l0, tree[ rt << 1 | 1 ].l1 );        swap( tree[ rt << 1 | 1 ].r0, tree[ rt << 1 | 1 ].r1 );        tree[rt].tag ^= 1;    }}void build( int l ,int r, int rt ) {     tree[rt].mark= -1;    if( l == r ) {        if( a[l] == 1 ) {            tree[rt].m1 = tree[rt].l1 = tree[rt].r1  = tree[rt].sum = 1;        } else {            tree[rt].m0 = tree[rt].l0 = tree[rt].r0 = 1;        }                   return;    }    int mid = ( l + r ) >> 1;    build( l, mid, rt << 1 );    build( mid + 1, r, rt << 1 | 1 );    pushup( l, r, rt );}void modify( int L, int R, int val, int l, int r, int rt ) {    if( L <= l && R >= r ) {        tree[rt].tag = 0;        tree[rt].mark = val;        tree[rt].sum = ( r - l + 1 ) * val;        if( val == 0 ) {            tree[rt].m1 = tree[rt].l1 = tree[rt].r1 = 0;            tree[rt].l0 = tree[rt].r0 = tree[rt].m0 = ( r - l + 1 );        } else {            tree[rt].m1 = tree[rt].l1 = tree[rt].r1 = r - l + 1;            tree[rt].l0 = tree[rt].r0 = tree[rt].m0 = 0;        }        return;    }    int mid = ( l + r ) >> 1;    pushdown( l, r, rt );    if( L <= mid ) modify( L, R, val, l, mid, rt << 1 );    if( R >  mid ) modify( L, R, val, mid + 1, r, rt << 1 | 1 );    pushup( l, r, rt );}void modify( int L, int R, int l, int r, int rt ) {    if( L <= l && R >= r ) {        tree[rt].tag ^= 1;        tree[rt].sum = ( r - l + 1 ) - tree[rt].sum;        swap( tree[rt].l0, tree[rt].l1 );        swap( tree[rt].r0, tree[rt].r1 );        swap( tree[rt].m1, tree[rt].m0 );        return;    }    int mid = ( l + r ) >> 1;    pushdown( l, r, rt );    if( L <= mid ) modify( L, R, l, mid, rt << 1 );    if( R >  mid ) modify( L, R, mid + 1, r, rt << 1 | 1 );    pushup( l, r, rt );}int query( int L, int R, int l, int r, int rt ) {    if( L <= l && R >= r ) { return tree[rt].sum; }    int mid = ( l + r ) >> 1;    pushdown( l, r, rt );    int tmp = 0;    if( L <= mid ) tmp += query( L, R, l, mid, rt << 1 );    if( R >  mid ) tmp += query( L, R, mid + 1, r, rt << 1 | 1 );    return tmp;}Tree comb( Tree lson, Tree rson, int l, int r ) {    Tree tmp;    tmp.len = ( r - l + 1 );    tmp.m1 = max( lson.m1, rson.m1 );    tmp.m1 = max( tmp.m1, lson.r1 + rson.l1 );    if( lson.m1 == lson.len ) tmp.l1 = lson.len + rson.l1;    else                      tmp.l1 = lson.l1;    if( rson.m1 == rson.len ) tmp.r1 = rson.len + lson.r1;    else                      tmp.r1 = rson.r1;    return tmp;}Tree quemx( int L, int R, int l, int r, int rt ) {    if( L <= l && R >= r ){ tree[rt].len = r - l + 1; return tree[rt]; }    int mid = ( l + r ) >> 1;    pushdown( l, r, rt );    Tree LL,RR,F;    if( L <= mid ) LL = quemx( L, R, l, mid, rt << 1 );    if( R >  mid ) RR = quemx( L, R, mid + 1, r, rt << 1 | 1 );    F = comb( LL, RR, max( l, L ), min( r, R ) );    return F ;}int main( ) {    scanf( "%d%d", &n, &m );    for( register int i = 1; i <= n; i++ ) scanf( "%d", &a[i] );    build( 1, n, 1 );    for( register int i = 1; i <= m; i++ ) { int opt, x, y; Tree tmp;        scanf( "%d%d%d", &opt, &x, &y ); x++, y++;        switch (opt) {            case 0 : modify( x, y, 0, 1, n, 1 ); break;            case 1 : modify( x, y, 1, 1, n, 1 ); break;            case 2 : modify( x, y, 1, n, 1 ); break;            case 3 : printf( "%d\n", query( x, y, 1, n, 1 ) ); break;            case 4 : tmp = quemx( x, y, 1, n, 1 ); printf( "%d\n", tmp.m1 ); break;        }    }    return 0;}

这里写图片描述

原创粉丝点击