1858: [Scoi2010]序列操作

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 3079  Solved: 1475
[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)

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

操作有点多
因为会出现反转,所以0和1的信息都要记录
0,1分别记录出现次数,左数最长长度,右数最长长度和区间最长长度
代码别写错就好

#include<cstdio>
#include<algorithm>
#include<iostream>
#define ll long long
#define inf 2147483647
#define N 100005
using namespace std;
struct node{
int sum[2],lm[2],rm[2],mx[2];
int l,r,cov,rev;
void sp(){
swap(sum[0],sum[1]);
swap(lm[0],lm[1]);
swap(rm[0],rm[1]);
swap(mx[0],mx[1]);
}
void init(){cov=-1;}
}t[N*4];int n,m;
void pushup(int u){
int l=u<<1,r=l|1;
for(int i=0;i<2;i++){
t[u].sum[i]=t[l].sum[i]+t[r].sum[i];
t[u].lm[i]=t[l].lm[i];
if(t[l].lm[i]==t[l].r-t[l].l+1)t[u].lm[i]+=t[r].lm[i];
t[u].rm[i]=t[r].rm[i];
if(t[r].rm[i]==t[r].r-t[r].l+1)t[u].rm[i]+=t[l].rm[i];
t[u].mx[i]=max(max(t[l].mx[i],t[r].mx[i]),t[l].rm[i]+t[r].lm[i]);
}
}
void swapp(int u){t[u].sp();}
void change(int u){
int k=t[u].cov,o=k^1;
t[u].sum[k]=t[u].lm[k]=t[u].rm[k]=t[u].mx[k]=t[u].r-t[u].l+1;
t[u].sum[o]=t[u].lm[o]=t[u].rm[o]=t[u].mx[o]=0;
}
void pushdown(int u){
int l=u<<1,r=l|1;
if(t[u].rev){
if(t[l].cov!=-1)t[l].cov^=1,swapp(l);
else t[l].rev^=1,swapp(l);
if(t[r].cov!=-1)t[r].cov^=1,swapp(r);
else t[r].rev^=1,swapp(r);
t[u].rev=0;
}
if(t[u].cov!=-1){
t[l].cov=t[r].cov=t[u].cov;
change(l);change(r);
t[u].cov=-1;
}
}
void build(int u,int l,int r){
t[u].l=l;t[u].r=r;t[u].init();
if(l==r){
int x;
scanf("%d",&x);int o=x^1;
t[u].sum[x]=t[u].lm[x]=t[u].rm[x]=t[u].mx[x]=1;
t[u].sum[o]=t[u].lm[o]=t[u].rm[o]=t[u].mx[o]=0;
return;
}
int mid=(l+r)>>1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
pushup(u);
}
void cover(int u,int l,int r,int op){
if(t[u].l==l&&t[u].r==r){
t[u].rev=0;
t[u].cov=op;
change(u);
return;
}
pushdown(u);
int mid=(t[u].l+t[u].r)>>1;
if(r<=mid)cover(u<<1,l,r,op);
else if(l>mid)cover(u<<1|1,l,r,op);
else{
cover(u<<1,l,mid,op);
cover(u<<1|1,mid+1,r,op);
}
pushup(u);
}
void reverse(int u,int l,int r){
if(t[u].l==l&&t[u].r==r){
if(t[u].cov!=-1){
t[u].cov^=1;
swapp(u);
return;
}
t[u].rev^=1;
swapp(u);
return;
}
pushdown(u);
int mid=(t[u].l+t[u].r)>>1;
if(r<=mid)reverse(u<<1,l,r);
else if(l>mid)reverse(u<<1|1,l,r);
else{
reverse(u<<1,l,mid);
reverse(u<<1|1,mid+1,r);
}
pushup(u);
}
int sum(int u,int l,int r){
if(t[u].l==l&&t[u].r==r)return t[u].sum[1];
pushdown(u);
int mid=(t[u].l+t[u].r)>>1;
if(r<=mid)return sum(u<<1,l,r);
else if(l>mid)return sum(u<<1|1,l,r);
return sum(u<<1,l,mid)+sum(u<<1|1,mid+1,r);
}
struct ans{int len,lm,rm,mx;};
ans query(int u,int l,int r){
if(t[u].l==l&&t[u].r==r){
ans p;
p=(ans){t[u].r-t[u].l+1,t[u].lm[1],t[u].rm[1],t[u].mx[1]};
return p;
}
pushdown(u);
int mid=(t[u].l+t[u].r)>>1;
if(r<=mid)return query(u<<1,l,r);
else if(l>mid)return query(u<<1|1,l,r);
else{
ans a=query(u<<1,l,mid);
ans b=query(u<<1|1,mid+1,r);
ans k=(ans){a.len+b.len,a.lm,b.rm,a.mx};
if(a.lm==a.len)k.lm+=b.lm;
if(b.rm==b.len)k.rm+=a.rm;
k.mx=max(k.mx,max(b.mx,a.rm+b.lm));
return k;
}
}
int main(){
scanf("%d%d",&n,&m);
build(1,1,n);
for(int i=1;i<=m;i++){
int op,l,r;
scanf("%d%d%d",&op,&l,&r);l++;r++;
if(op==1||op==0)cover(1,l,r,op);
if(op==2)reverse(1,l,r);
if(op==3)printf("%d\n",sum(1,l,r));
if(op==4){
ans a=query(1,l,r);
printf("%d\n",a.mx);
}
}
return 0;
}

bzoj1858[Scoi2010]序列操作 线段树的更多相关文章

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

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1858 线段树...调了一个上午...(后面带 // 的都是改出来的) lazy 标记的下放好 ...

  2. 【BZOJ-1858】序列操作 线段树

    1858: [Scoi2010]序列操作 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1961  Solved: 991[Submit][Status ...

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

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

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

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

  5. Luogu P2572 [SCOI2010]序列操作 线段树。。

    咕咕了...于是借鉴了小粉兔的做法ORZ... 其实就是维护最大子段和的线段树,但上面又多了一些操作....QWQ 维护8个信息:1/0的个数(sum),左/右边起1/0的最长长度(ls,rs),整段 ...

  6. 洛谷$P2572\ [SCOI2010]$ 序列操作 线段树/珂朵莉树

    正解:线段树/珂朵莉树 解题报告: 传送门$w$ 本来是想写线段树的,,,然后神仙$tt$跟我港可以用珂朵莉所以决定顺便学下珂朵莉趴$QwQ$ 还是先写线段树做法$QwQ$? 操作一二三四都很$eas ...

  7. [SCOI2010]序列操作 线段树

    ---题面--- 题解: 在考场上打的这道题,出人意料的很快就打完了?! 直接用线段树,维护几个东西: 1,lazy标记 : 表示区间赋值 2,mark标记:表示区间翻转 3,l1:前缀最长连续的1的 ...

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

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

  9. BZOJ1858 [Scoi2010]序列操作(线段树)

    题目链接 [Scoi2010]序列操作 考验代码能力的一道好题. 思想还是很简单的(直接上线段树),但是比较难写. #include <bits/stdc++.h> using names ...

随机推荐

  1. css3 文字的设置

    1.text-shadow 有3个length参数,第1个表示水平偏移,第2个表示垂直偏移,第3个表示模糊(可选) .text11{text-shadow: 3px 3px 5px #f00 ;col ...

  2. 在Windows上安装「算法 第四版」组件

    这篇文档将向你介绍如何在Windows系统上安装本书将用到的Java开发环境,同时我们也提供了一个手把手的.使用我们提供的DrJava工具或者用命令行来创建.编译和运行你的第一个Java程序的手册,这 ...

  3. AWS EMR上搭建HBase环境

    0. 概述 AWS的EMR服务为客户提供的托管 Hadoop 框架可以让您轻松.快 速.经济高效地在多个动态可扩展的 Amazon EC2 实例之间分发和处理 大量数据.您还可以运行其他常用的分发框架 ...

  4. Packet for query is too large (84 > -1).

    windows下的resin配置连接mysql,常用的安全的做法是将数据库信息配置到conf目录下的resin.xml文件中. 因为resin连接mysql不是必须的,所以resin本身没有提供mys ...

  5. ubuntu1604使用源码方式安装ruby2.5.0

    本文介绍ubutntu1604环境下源代码方式安装ruby 版本2.5.0 如果内存小于2G可以开启虚拟内存,下面的命令开启4G虚拟内存 sudo dd if=/dev/zero of=/swap b ...

  6. 数据恢复案例分享:MSSQL 2000 错误823

    一.故障描述 MSSQL Server 2000 附加数据库错误823,附加数据库失败.数据库没有备份,不能通过备份恢复数据库,急需恢复数据库中的数据. 二.故障分析SQL Server数据库 823 ...

  7. nyoj 黑色帽子

    黑色帽子 时间限制:1000 ms  |  内存限制:65535 KB 难度:1   描述         最近发现了一个搞笑的游戏,不过目前还没玩过.一个舞会上,每个人头上都戴着一顶帽子,帽子只有黑 ...

  8. vue mint-ui 三级地址联动

    我也是第一次写这种地址联动的 刚开始的时候 我还以为直接用select来写 后来公司的ios告知并不是这样的 他说应该时这样的 于是第一想法 赶紧找插件吧 但是找了一会未果  就问了公司大神 他刚开始 ...

  9. $(function(){})和window.onload的区别

    (1)$(function(){}):DOM节点创建 完成才执行 (2)window.onload:页面所有资源(JS/CSS)加载完成才执行

  10. win10 系统右键菜单不显示文字(只有小图标)修复方法

    如下图,win10点击鼠标右键调出菜单时,看不到菜单的文字,只显示了小图标. 解决方法: Cortana 搜索 cmd ,看到 命令提示符,右键,选择 以管理员身份运行. 在命令提示符里输入以下命令, ...