bzoj1858 [Scoi2010]序列操作——线段树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1858
线段树...调了一个上午...(后面带 // 的都是改出来的)
lazy 标记的下放好麻烦,还得考虑赋值和取反的先后顺序什么的...
因为在取反时把赋值标记 swap 了,所以下放的时候先判断取反再判断赋值...
而且WA了一上午的原因竟然是一开始不慎把取反以为成翻转了,后来没改干净...那个 rev 的名字啊...
总之没有太改变自己最初的想法、改了些细节就A了还是很高兴的!
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int const maxn=1e5+;
int n,m,op,a,b,c[maxn];
struct N{
int sum,z[],y[],m[];
int lz[],rev,len;
}t[maxn<<];
int rd()
{
int ret=;char ch=getchar();
while(ch<''||ch>'')ch=getchar();
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return ret;
}
void pushup(int x)
{
int ls=(x<<),rs=(x<<|);
t[x].sum=t[ls].sum+t[rs].sum;
for(int i=;i<=;i++)
{
t[x].z[i]=t[ls].z[i]+(t[ls].z[i]==t[ls].len?t[rs].z[i]:);
t[x].y[i]=t[rs].y[i]+(t[rs].y[i]==t[rs].len?t[ls].y[i]:);
// t[x].m[i]=max(max(t[x].z[i],t[x].y[i]),t[ls].y[i]+t[rs].z[i]);//
t[x].m[i]=max(max(t[ls].m[i],t[rs].m[i]),t[ls].y[i]+t[rs].z[i]);//
}
}
void upt(int x,int val)//赋值
{
t[x].lz[val]=;
t[x].lz[!val]=; t[x].rev=;//!
t[x].sum=t[x].len*val;
t[x].z[val]=t[x].y[val]=t[x].m[val]=t[x].len;
t[x].z[!val]=t[x].y[!val]=t[x].m[!val]=;
}
void re(int x)//取反
{
swap(t[x].z[],t[x].z[]); swap(t[x].y[],t[x].y[]);//!!!
swap(t[x].m[],t[x].m[]);
t[x].sum=t[x].len-t[x].sum; t[x].rev^=;
swap(t[x].lz[],t[x].lz[]);//!
}
void pushdown(int x)
{
// if(t[x].len==1)return;//
int ls=(x<<),rs=(x<<|);
if(t[x].rev)t[x].rev^=,re(ls),re(rs);
for(int v=;v<=;v++)
if(t[x].lz[v])t[x].lz[v]=,upt(ls,v),upt(rs,v);//顺序
}
void build(int x,int l,int r)
{
t[x].len=r-l+;
if(l==r)
{
t[x].z[c[l]]=t[x].y[c[l]]=t[x].m[c[l]]=;
t[x].sum=c[l]; //
return;
}
int mid=((l+r)>>);
build(x<<,l,mid); build(x<<|,mid+,r);
pushup(x);
}
void update(int x,int l,int r,int L,int R,int val)
{
if(l>=L&&r<=R)
{
upt(x,val);return;
}
pushdown(x);
int mid=((l+r)>>);
if(mid>=L)update(x<<,l,mid,L,R,val);
if(mid<R)update(x<<|,mid+,r,L,R,val);
pushup(x);
}
void rever(int x,int l,int r,int L,int R)
{
if(l>=L&&r<=R)
{
re(x);return;
}
int mid=((l+r)>>);
pushdown(x);
if(mid>=L)rever(x<<,l,mid,L,R);
if(mid<R)rever(x<<|,mid+,r,L,R);
pushup(x);
}
int query(int x,int l,int r,int L,int R)
{
if(l>=L&&r<=R)return t[x].sum;
int mid=((l+r)>>),ret=;
pushdown(x);
if(mid>=L)ret+=query(x<<,l,mid,L,R);
if(mid<R)ret+=query(x<<|,mid+,r,L,R);
return ret;
}
int ask(int x,int l,int r,int L,int R)
{
if(l>=L&&r<=R)return t[x].m[];
pushdown(x);//
int mid=((l+r)>>);
if(mid>=R)return ask(x<<,l,mid,L,R);
if(mid<L)return ask(x<<|,mid+,r,L,R);
int ret=;
ret=max(ask(x<<,l,mid,L,R),ask(x<<|,mid+,r,L,R));
ret=max(ret,min(t[x<<].y[],mid-L+)+min(t[x<<|].z[],R-mid));
return ret;
}
int main()
{
n=rd();m=rd();
for(int i=;i<=n;i++)c[i]=rd();
build(,,n);
while(m--)
{
op=rd(); a=rd()+; b=rd()+;
if(op==||op==)update(,,n,a,b,op);
if(op==)rever(,,n,a,b);
if(op==)printf("%d\n",query(,,n,a,b));
if(op==)printf("%d\n",ask(,,n,a,b));
}
return ;
}
bzoj1858 [Scoi2010]序列操作——线段树的更多相关文章
- bzoj1858[Scoi2010]序列操作 线段树
1858: [Scoi2010]序列操作 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 3079 Solved: 1475[Submit][Statu ...
- 【BZOJ-1858】序列操作 线段树
1858: [Scoi2010]序列操作 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1961 Solved: 991[Submit][Status ...
- BZOJ 1858: [Scoi2010]序列操作( 线段树 )
略恶心的线段树...不过只要弄清楚了AC应该不难.... ---------------------------------------------------------------- #inclu ...
- 【bzoj1858】[Scoi2010]序列操作 线段树区间合并
题目描述 lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作: 0 a b 把[a, b]区间内的所有数全变成0 1 a b ...
- Luogu P2572 [SCOI2010]序列操作 线段树。。
咕咕了...于是借鉴了小粉兔的做法ORZ... 其实就是维护最大子段和的线段树,但上面又多了一些操作....QWQ 维护8个信息:1/0的个数(sum),左/右边起1/0的最长长度(ls,rs),整段 ...
- 洛谷$P2572\ [SCOI2010]$ 序列操作 线段树/珂朵莉树
正解:线段树/珂朵莉树 解题报告: 传送门$w$ 本来是想写线段树的,,,然后神仙$tt$跟我港可以用珂朵莉所以决定顺便学下珂朵莉趴$QwQ$ 还是先写线段树做法$QwQ$? 操作一二三四都很$eas ...
- [SCOI2010]序列操作 线段树
---题面--- 题解: 在考场上打的这道题,出人意料的很快就打完了?! 直接用线段树,维护几个东西: 1,lazy标记 : 表示区间赋值 2,mark标记:表示区间翻转 3,l1:前缀最长连续的1的 ...
- 【题解】P4247 [清华集训]序列操作(线段树修改DP)
[题解]P4247 [清华集训]序列操作(线段树修改DP) 一道神仙数据结构(DP)题. 题目大意 给定你一个序列,会区间加和区间变相反数,要你支持查询一段区间内任意选择\(c\)个数乘起来的和.对1 ...
- BZOJ1858 [Scoi2010]序列操作(线段树)
题目链接 [Scoi2010]序列操作 考验代码能力的一道好题. 思想还是很简单的(直接上线段树),但是比较难写. #include <bits/stdc++.h> using names ...
随机推荐
- POJ3621 Sightseeing Cows【最短路】
题目大意:在一个无向图里找一个环,是的点权和除以边权和最大 思路:UVA11090姊妹题 事实上当这题点权和都为1时就是上一题TUT #include <stdio.h> #include ...
- PHP 常见问题3
1,Http 和 Https 的区别 第一:http 是超文本传输协议,信息是明文传输,https 是具有安全性的 ssl 加密传输协议 第二:http 和 https 使用的是完全不同的连接方式,端 ...
- poj 1236+hdu2767 有向图 缩点+看度数(tarjan)
1236题意:一个有向图,1,求至少从几个点出发可以遍历该图,2:,求至少添加多少边,使强连通.而,HDU的只有后面一问. 解;先缩点,第一问只需找所有入度为0的点即可.,第2问,max(入度为0的点 ...
- 前端学习之-- Jquery
Jquery学习笔记 中文参考文档:http://jquery.cuishifeng.cn Jquery是一个包含DOM/BOM/JavaScript的类库引入jquery文件方法:<scrip ...
- 【Java源码】集合类-ArrayDeque
一.类继承关系 ArrayDeque和LinkedList一样都实现了双端队列Deque接口,但它们内部的数据结构和使用方法却不一样.根据该类的源码注释翻译可知: ArrayDeque实现了Deque ...
- c++ static const
static 是c++中很常用的修饰符,它被用来控制变量的存储方式和可见性,下面我将从 static 修饰符的产生原因.作用谈起,全面分析static 修饰符的实质. static 的两大作用: 一. ...
- eclipse工程设置项目jre
Eclipse 是一个开放源代码的.基于Java的可扩展开发平台.就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境.当我们导入已经存在项目或者通过svn引入项目时经常出现红叉叉的情 ...
- 再说javascript 的__proto__ 和prototype 属性
过了一段时间,没写 原生的 javascript 的了,感觉天天在用框架写代码,框架写代码完全限定死了你所需要思考的东西,只是在处理一些业务逻辑,真正的代码 都感觉不会写了. 突然发现,框架用的不熟悉 ...
- Exchanger使用
Exchanger使用
- DRBD原理知识
DRBD(Distributed Relicated Block Device 分布式复制块设备), 可以解决磁盘单点故障.一般情况下只支持2个节点. 大致工作原理如下图: 一般情况下文件写入磁盘的步 ...