1858: [Scoi2010]序列操作

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 1961  Solved: 991
[Submit][Status][Discuss]

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<n)表示对于区间[a, b]执行标号为op的操作="" <="" div="">

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

Solution

线段树裸题,但是...

维护各种量:左/右端点,区间大小,覆盖标记,翻转标记,1/0的数量,连续出现次数,左右段的量,是否完全覆盖....

标记之间各种相互作用...比如 覆盖标记时清零翻转标记...

向上更新值的时候,不太同于以往..分类讨论左右段来合并..

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 100010
inline int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
int n,m;
struct Treenode{int tag,rev,l,r,size,sum[],L[],R[],num[],da;}tree[maxn<<];
inline Treenode merge(Treenode a,Treenode b)
{
Treenode re;
re.l=a.l; re.r=b.r; re.size=re.r-re.l+; re.rev=; re.tag=-;
re.L[]=a.L[]; re.L[]=a.L[]; re.R[]=b.R[]; re.R[]=b.R[];
re.num[]=max(a.num[],b.num[]); re.num[]=max(a.num[],b.num[]);
re.num[]=max(re.num[],a.R[]+b.L[]); re.num[]=max(re.num[],a.R[]+b.L[]);
re.sum[]=a.sum[]+b.sum[]; re.sum[]=a.sum[]+b.sum[];
if(a.da==) re.L[]=a.num[]+b.L[]; else if(a.da==) re.L[]=a.num[]+b.L[];
if(b.da==) re.R[]=b.num[]+a.R[]; else if(b.da==) re.R[]=b.num[]+a.R[];
if(a.da==b.da) re.da=a.da; else re.da=-;
return re;
}
inline void update(int now)
{
tree[now]=merge(tree[now<<],tree[now<<|]);
}
inline void build(int k,int l,int r)
{
tree[k].l=l;tree[k].r=r;
tree[k].tag=-; tree[k].size=r-l+;
if(l==r)
{
scanf("%d",&tree[k].da);
if(tree[k].da)
{tree[k].L[]=tree[k].R[]=tree[k].num[]=tree[k].sum[]=;}
else
{tree[k].L[]=tree[k].R[]=tree[k].num[]=tree[k].sum[]=;}
return;
}
int mid=(l+r)>>;
build(k<<,l,mid);build(k<<|,mid+,r);
update(k);
}
inline void paintrev(int now)
{
swap(tree[now].L[],tree[now].L[]);
swap(tree[now].R[],tree[now].R[]);
swap(tree[now].num[],tree[now].num[]);
swap(tree[now].sum[],tree[now].sum[]);
if (tree[now].da!=-) tree[now].da^=;
}
inline void painttag(int now,int D)
{
tree[now].rev=;
if (D!=)
{
tree[now].sum[]=tree[now].L[]=tree[now].R[]=tree[now].num[]=,
tree[now].sum[]=tree[now].L[]=tree[now].R[]=tree[now].num[]=tree[now].size;
}
else
{
tree[now].sum[]=tree[now].L[]=tree[now].R[]=tree[now].num[]=tree[now].size,
tree[now].sum[]=tree[now].L[]=tree[now].R[]=tree[now].num[]=;
}
tree[now].da=D;
}
inline void pushdown(int now)
{
if (tree[now].l==tree[now].r) return;
if (tree[now].tag!=-)
{
tree[now<<].tag=tree[now<<|].tag=tree[now].tag;
painttag(now<<,tree[now].tag); painttag(now<<|,tree[now].tag); tree[now].tag=-;
}
if (tree[now].rev)
{
tree[now<<].rev^=; tree[now<<|].rev^=;
paintrev(now<<); paintrev(now<<|); tree[now].rev=;
}
}
inline void change(int now,int L,int R,int D)
{
pushdown(now);
if(tree[now].l==L && tree[now].r==R) {painttag(now,D);tree[now].tag=D;return;}
int mid=(tree[now].l+tree[now].r)>>;
if(mid>=R) change(now<<,L,R,D);
else if(mid<L) change(now<<|,L,R,D);
else change(now<<,L,mid,D),change(now<<|,mid+,R,D);
update(now);
}
inline void reserv(int now,int L,int R)
{
pushdown(now);
if(tree[now].l==L && tree[now].r==R) {paintrev(now);tree[now].rev^=;return;}
int mid=(tree[now].l+tree[now].r)>>;
if(mid>=R) reserv(now<<,L,R);
else if(mid<L) reserv(now<<|,L,R);
else reserv(now<<,L,mid),reserv(now<<|,mid+,R);
update(now);
}
inline int asksum(int now,int L,int R)
{
pushdown(now);
if(tree[now].l==L && tree[now].r==R) return tree[now].sum[];
int mid=(tree[now].l+tree[now].r)>>;
if(mid>=R) return asksum(now<<,L,R);
else if(mid<L) return asksum(now<<|,L,R);
else return asksum(now<<,L,mid)+asksum(now<<|,mid+,R);
update(now);
}
inline Treenode asknum(int now,int L,int R)
{
pushdown(now);
if (L==tree[now].l && R==tree[now].r) return tree[now];
int mid=(tree[now].l+tree[now].r)>>;
if (mid>=R) return asknum(now<<,L,R);
else if(mid<L)return asknum(now<<|,L,R);
else return merge(asknum(now<<,L,mid),asknum(now<<|,mid+,R));
}
int main()
{
n=read(),m=read();build(,,n);
while (m--)
{
int opt=read(),l=read(),r=read(); l++;r++;
switch (opt)
{
case : change(,l,r,);break;
case : change(,l,r,);break;
case : reserv(,l,r);break;
case : printf("%d\n",asksum(,l,r));break;
case : printf("%d\n",asknum(,l,r).num[]);break;
}
}
return ;
}

手一点误就调好久,巨恶心..  自己讨论的不够好..还重敲了一遍....至于压代码?Char哥比我短80行..

【BZOJ-1858】序列操作 线段树的更多相关文章

  1. bzoj 2962 序列操作——线段树(卷积?)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2962 如果 _,_,_,…… 变成了 (_+k),(_+k),(_+k),…… ,计算就是在 ...

  2. bzoj 2962 序列操作 —— 线段树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2962 维护 sum[i] 表示选 i 个的乘积和,合并两个子树就枚举两边选多少,乘起来即可: ...

  3. bzoj 1858 序列操作

    bzoj 1858 序列操作 带有随机多个区间单值覆盖的区间操作题,可考虑用珂朵莉树解决. #include<bits/stdc++.h> using namespace std; #de ...

  4. 【题解】P4247 [清华集训]序列操作(线段树修改DP)

    [题解]P4247 [清华集训]序列操作(线段树修改DP) 一道神仙数据结构(DP)题. 题目大意 给定你一个序列,会区间加和区间变相反数,要你支持查询一段区间内任意选择\(c\)个数乘起来的和.对1 ...

  5. BZOJ 1858: [Scoi2010]序列操作( 线段树 )

    略恶心的线段树...不过只要弄清楚了AC应该不难.... ---------------------------------------------------------------- #inclu ...

  6. 【BZOJ-2962】序列操作 线段树 + 区间卷积

    2962: 序列操作 Time Limit: 50 Sec  Memory Limit: 256 MBSubmit: 678  Solved: 246[Submit][Status][Discuss] ...

  7. 【bzoj1858】[Scoi2010]序列操作 线段树区间合并

    题目描述 lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作: 0 a b 把[a, b]区间内的所有数全变成0 1 a b ...

  8. 【BZOJ2962】序列操作 线段树

    [BZOJ2962]序列操作 Description 有一个长度为n的序列,有三个操作1.I a b c表示将[a,b]这一段区间的元素集体增加c,2.R a b表示将[a,b]区间内所有元素变成相反 ...

  9. bzoj1858[Scoi2010]序列操作 线段树

    1858: [Scoi2010]序列操作 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 3079  Solved: 1475[Submit][Statu ...

随机推荐

  1. Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.

    Validation failed for one or more entities. See 'EntityValidationErrors' property for more details. ...

  2. Codevs 1910递归函数

    1910 递归函数  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题目描述 Description 对于一个递归函数w(a, b, c). 如果a <= ...

  3. mongodb分布式查询

    分布式查询:mongodb的分布式模型分为replica set和sharded cluster. sharded集群中将read根据sharding key(分片键)转发到指定的shard节点,re ...

  4. Ros与Vrep平台搭建

    参考资料: ROS安装: ros 是一个framework 和Android有点像,内核用的linux.Ros提供了一种供机器人开发者迅速上手的一个平台, 可以快速搭建自己的应用,利用ros下面自带的 ...

  5. spring:如何用代码动态向容器中添加或移除Bean ?

    先来看一张类图: 有一个业务接口IFoo,提供了二个实现类:FooA及FooB,默认情况下,FooA使用@Component由Spring自动装配,如果出于某种原因,在运行时需要将IFoo的实现,则F ...

  6. Openwrt dnsmasq 设置要点

    之前设置dnsmasq,一直没有奏效,后来摸索了一下,初步发现它的原理: 正常的流程应该是像这样的,先由client来发送DNS请求到网关,然后网关的dnsmasq处理这个请求, 再根据设置决定如何处 ...

  7. Infer.net 开源组件: 1, 机器学习入门,要从贝叶斯说起

    我的入门方式,先从应用现象中,总结规律反推本质.一头扎进理论书籍是不对的. 老外的先进,还是体现在传承方面.没办法,我们竞争压力大,有好东西藏着掖着.大家都苦逼 我最开始是从介绍,有了基本概念,见xx ...

  8. gulp插件gulp-usemin简单使用

    关于什么是gulp,它和grunt有什么区别等问题,这里不做任何介绍.本文主要介绍如何使用gulp-usemin这款插件,同时也会简单介绍本文中用到的一些插件. 什么是gulp-usemin 用来将H ...

  9. (二十一)状态模式详解(DOTA版)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 本次LZ给各位介绍状态模式, ...

  10. Verilog代码规范I

    Verilog代码规范I "规范"这问题 "规范"这个富含专业气息的词汇(个人感觉),其实规范这种东西,就是大家都约定熟成的东西,一旦你不遵守这个东西,专业人士 ...