【BZOJ-1858】序列操作 线段树
1858: [Scoi2010]序列操作
Time Limit: 10 Sec Memory Limit: 64 MB
Submit: 1961 Solved: 991
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
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
2
6
5
HINT
对于30%的数据,1<=n, m<=1000
对于100%的数据,1<=n, m<=100000
Source
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】序列操作 线段树的更多相关文章
- bzoj 2962 序列操作——线段树(卷积?)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2962 如果 _,_,_,…… 变成了 (_+k),(_+k),(_+k),…… ,计算就是在 ...
- bzoj 2962 序列操作 —— 线段树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2962 维护 sum[i] 表示选 i 个的乘积和,合并两个子树就枚举两边选多少,乘起来即可: ...
- bzoj 1858 序列操作
bzoj 1858 序列操作 带有随机多个区间单值覆盖的区间操作题,可考虑用珂朵莉树解决. #include<bits/stdc++.h> using namespace std; #de ...
- 【题解】P4247 [清华集训]序列操作(线段树修改DP)
[题解]P4247 [清华集训]序列操作(线段树修改DP) 一道神仙数据结构(DP)题. 题目大意 给定你一个序列,会区间加和区间变相反数,要你支持查询一段区间内任意选择\(c\)个数乘起来的和.对1 ...
- BZOJ 1858: [Scoi2010]序列操作( 线段树 )
略恶心的线段树...不过只要弄清楚了AC应该不难.... ---------------------------------------------------------------- #inclu ...
- 【BZOJ-2962】序列操作 线段树 + 区间卷积
2962: 序列操作 Time Limit: 50 Sec Memory Limit: 256 MBSubmit: 678 Solved: 246[Submit][Status][Discuss] ...
- 【bzoj1858】[Scoi2010]序列操作 线段树区间合并
题目描述 lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作: 0 a b 把[a, b]区间内的所有数全变成0 1 a b ...
- 【BZOJ2962】序列操作 线段树
[BZOJ2962]序列操作 Description 有一个长度为n的序列,有三个操作1.I a b c表示将[a,b]这一段区间的元素集体增加c,2.R a b表示将[a,b]区间内所有元素变成相反 ...
- bzoj1858[Scoi2010]序列操作 线段树
1858: [Scoi2010]序列操作 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 3079 Solved: 1475[Submit][Statu ...
随机推荐
- 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. ...
- Codevs 1910递归函数
1910 递归函数 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 对于一个递归函数w(a, b, c). 如果a <= ...
- mongodb分布式查询
分布式查询:mongodb的分布式模型分为replica set和sharded cluster. sharded集群中将read根据sharding key(分片键)转发到指定的shard节点,re ...
- Ros与Vrep平台搭建
参考资料: ROS安装: ros 是一个framework 和Android有点像,内核用的linux.Ros提供了一种供机器人开发者迅速上手的一个平台, 可以快速搭建自己的应用,利用ros下面自带的 ...
- spring:如何用代码动态向容器中添加或移除Bean ?
先来看一张类图: 有一个业务接口IFoo,提供了二个实现类:FooA及FooB,默认情况下,FooA使用@Component由Spring自动装配,如果出于某种原因,在运行时需要将IFoo的实现,则F ...
- Openwrt dnsmasq 设置要点
之前设置dnsmasq,一直没有奏效,后来摸索了一下,初步发现它的原理: 正常的流程应该是像这样的,先由client来发送DNS请求到网关,然后网关的dnsmasq处理这个请求, 再根据设置决定如何处 ...
- Infer.net 开源组件: 1, 机器学习入门,要从贝叶斯说起
我的入门方式,先从应用现象中,总结规律反推本质.一头扎进理论书籍是不对的. 老外的先进,还是体现在传承方面.没办法,我们竞争压力大,有好东西藏着掖着.大家都苦逼 我最开始是从介绍,有了基本概念,见xx ...
- gulp插件gulp-usemin简单使用
关于什么是gulp,它和grunt有什么区别等问题,这里不做任何介绍.本文主要介绍如何使用gulp-usemin这款插件,同时也会简单介绍本文中用到的一些插件. 什么是gulp-usemin 用来将H ...
- (二十一)状态模式详解(DOTA版)
作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 本次LZ给各位介绍状态模式, ...
- Verilog代码规范I
Verilog代码规范I "规范"这问题 "规范"这个富含专业气息的词汇(个人感觉),其实规范这种东西,就是大家都约定熟成的东西,一旦你不遵守这个东西,专业人士 ...