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;}
- BZOJ 1858 SCOI2010 序列操作 线段树
- BZOJ 1858 [Scoi2010]序列操作 线段树
- 【bzoj 1858】 [Scoi2010]序列操作 线段树
- bzoj 1858: [Scoi2010]序列操作 线段树
- BZOJ 1858 [Scoi2010]序列操作 线段树
- BZOJ 1858 [Scoi2010]序列操作 线段树
- BZOJ 1858: [Scoi2010]序列操作 线段树
- BZOJ 1858: [Scoi2010]序列操作 线段树
- bzoj 1858: [Scoi2010]序列操作(线段树)
- BZOJ 1858: [Scoi2010]序列操作 线段树区间修改查询
- [BZOJ 1858][Scoi2010]序列操作(线段树)
- 【BZOJ】【P1858】【Scoi2010】【序列操作】【题解】【线段树】
- 1858: [Scoi2010]序列操作 线段树
- 【BZOJ 1858】 [Scoi2010]序列操作
- BZOJ 1858 [Scoi2010]序列操作
- bzoj 1858: [Scoi2010]序列操作
- BZOJ 1858 [Scoi2010]序列操作
- 【SCOI2010】【线段树】序列操作
- ISO/IEC 14496 文档内容 简介
- css3基础
- 如何学习spring入门知识点.
- jquery的封装ajax的get请求
- android-ramdisk.img分析、recovery.img&boot.img执行过程
- BZOJ 1858: [Scoi2010]序列操作 线段树
- Leetcode算法学习日志-455 Assign Cookies
- C语言再学习--关键字
- Rotating Scoreboard POJ
- JAVA接口声明
- hdu 3516(四边形优化dp)
- python--统计列表中不同元素的数量
- 《程序设计入门—Java语言.翁恺》第三周编程作业(2)-数字特征值
- Recovery启动流程(2)---UI界面