/*
一开始维护了两个标记 开了两个数组
想的是 可能当前两种操作都要做
但是太复杂了 不好处理
其实 当前要做的标记可以只有一个 我们在Insert的时候 要打的标记是2即翻转区间: 1.如果原来是区间赋值1 先赋值1在翻转 问题不大 标记变 1-1=0
2.如果原来是区间赋值0 同上 问题不大 标记 1-0=1
3.如果原始是区间翻转 抵消1-2=-1
4.如果原来是-1 无标记 就打上 1-(-1)=2 这个时候要先把区间的01信息互换 要打的标记是01即区间赋值
就无视之前的翻转操作 直接打上标记更新k 然后Up的时候(标记下方)就只有一个标记
1.如果是2 就下放 改了左右儿子 然后同上进行标记改变
2.如果是01
*/
#include<cstdio>
#include<cstring>
#include<iostream>
#define lc k*2
#define rc k*2+1
#define len (r-l+1)
#define mid (l+r)/2
#define maxn 400010
using namespace std;
int T,I,n,m,s1[maxn],s0[maxn],l1[maxn],l0[maxn],r1[maxn],r0[maxn],mx1[maxn],mx0[maxn],a[maxn];
void Swap(int k,int l,int r){
a[k]=-a[k];swap(s1[k],s0[k]);swap(l1[k],l0[k]);
swap(r1[k],r0[k]);swap(mx1[k],mx0[k]);
}
void Up(int k,int l,int r){
if(a[k]==){
a[k]=-;Swap(lc,l,mid);Swap(rc,mid+,r);return;
}
a[lc]=a[rc]=a[k];
s1[lc]=(mid-l+)*a[k];s0[lc]=(mid-l+)*(a[k]^);
s1[rc]=(r-mid)*a[k];s0[rc]=(r-mid)*(a[k]^);
l1[lc]=(mid-l+)*a[k];l0[lc]=(mid-l+)*(a[k]^);
l1[rc]=(r-mid)*a[k];l0[rc]=(r-mid)*(a[k]^);
r1[lc]=(mid-l+)*a[k];r0[lc]=(mid-l+)*(a[k]^);
r1[rc]=(r-mid)*a[k];r0[rc]=(r-mid)*(a[k]^);
mx1[lc]=(mid-l+)*a[k];mx0[lc]=(mid-l+)*(a[k]^);
mx1[rc]=(r-mid)*a[k];mx0[rc]=(r-mid)*(a[k]^);
a[k]=-;
}
void Insert(int k,int l,int r,int x,int y,int z){
if(x<=l&&y>=r){
if(z==)Swap(k,l,r);
else {
a[k]=z;s1[k]=len*z;s0[k]=len*(z^);mx1[k]=len*z;mx0[k]=len*(z^);
l1[k]=len*z;l0[k]=len*(z^);r1[k]=len*z;r0[k]=len*(z^);
}
return;
}
if(a[k]!=-)Up(k,l,r);
if(x<=mid)Insert(lc,l,mid,x,y,z);
if(y>mid)Insert(rc,mid+,r,x,y,z);
s1[k]=s1[lc]+s1[rc];s0[k]=s0[lc]+s0[rc];
l1[k]=l1[lc]+(l1[lc]==mid-l+)*l1[rc];
r1[k]=r1[rc]+(r1[rc]==r-mid)*r1[lc];
l0[k]=l0[lc]+(l0[lc]==mid-l+)*l0[rc];
r0[k]=r0[rc]+(r0[rc]==r-mid)*r0[lc];
mx1[k]=max(mx1[lc],max(mx1[rc],r1[lc]+l1[rc]));
mx0[k]=max(mx0[lc],max(mx0[rc],r0[lc]+l0[rc]));
}
int Query1(int k,int l,int r,int x,int y){
if(x<=l&&y>=r)return s1[k];
int res=;
if(a[k]!=-)Up(k,l,r);
if(x<=mid)res+=Query1(lc,l,mid,x,y);
if(y>mid)res+=Query1(rc,mid+,r,x,y);
return res;
}
int Query2(int k,int l,int r,int x,int y){
if(x<=l&&y>=r)return mx1[k];
if(a[k]!=-)Up(k,l,r);
int res=;
if(x<=mid)res=max(res,Query2(lc,l,mid,x,y));
if(y>mid)res=max(res,Query2(rc,mid+,r,x,y));
if(x<=mid&&y>mid)res=max(res,min(mid-x+,r1[lc])+min(y-mid,l1[rc]));
return res;
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);int x,y,z;
for(int i=;i<=n*;i++)a[i]=-;
for(int i=;i<=n;i++){
scanf("%d",&x);Insert(,,n,i,i,x);
}
for(I=;I<=m;I++){
scanf("%d%d%d",&z,&x,&y);x++;y++;
if(z==||z==||z==)Insert(,,n,x,y,z);
if(z==)printf("%d\n",Query1(,,n,x,y));
if(z==)printf("%d\n",Query2(,,n,x,y));
}
}
return ;
}

HDU 3397 Sequence operation 多标记线段树的更多相关文章

  1. HDU 3397 Sequence operation(线段树)

    HDU 3397 Sequence operation 题目链接 题意:给定一个01序列,有5种操作 0 a b [a.b]区间置为0 1 a b [a,b]区间置为1 2 a b [a,b]区间0变 ...

  2. hdu 3397 Sequence operation (线段树 区间合并 多重标记)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=3397 题意: 给你一串01串,有5种操作 0. 区间全部变为0 1.区间全部变为1 2.区间异或 3.询问 ...

  3. hdu 3397 Sequence operation(线段树:区间更新)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3397 题意:给你一个长度为n的0,1序列,支持下列五种操作, 操作0(0 a b):将a到b这个区间的 ...

  4. hdu 3397 Sequence operation(很有意思的线段树题)

    Sequence operation Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  5. 【线段树】HDU 3397 Sequence operation 区间合并

    操作 Change operations: 0 a b change all characters into '0's in [a , b] 1 a b change all characters i ...

  6. (简单) HDU 3397 Sequence operation,线段树+区间合并。

    Problem Description lxhgww got a sequence contains n characters which are all '0's or '1's. We have ...

  7. hdu 3397 Sequence operation 线段树

    题目链接 给出n个数, 每个数是0或1, 给5种操作, 区间变为1, 区间变为0, 区间0,1翻转, 询问区间内1的个数, 询问区间内最长连续1的个数. 需要将数组开成二维的, 然后区间0, 1翻转只 ...

  8. HDU 3397"Sequence operation"(线段树区间和并)

    传送门 •题意 给你一个仅包含 0 和 1 的序列: 在这个序列上有如下操作: (1)0 a b : 将 [a,b] 区间的数置 0: (2)1 a b : 将 [a,b] 区间的数置 1: (3)2 ...

  9. hdu 3397 Sequence operation 线段树 区间更新 区间合并

    题意: 5种操作,所有数字都为0或1 0 a b:将[a,b]置0 1 a b:将[a,b]置1 2 a b:[a,b]中的0和1互换 3 a b:查询[a,b]中的1的数量 4 a b:查询[a,b ...

随机推荐

  1. C++中 list与vector的区别

    引用http://www.cnblogs.com/shijingjing07/p/5587719.html C++ vector和list的区别 1.vector数据结构vector和数组类似,拥有一 ...

  2. [ SDOI 2009 ] HH的项链 & [ HEOI 2012 ] 采花

    \(\\\) \(Description\) 给出一个长为\(N\)的序列,\(M\)次询问区间\([L_i,R_i]\)内不同数字的个数. \(N\in [1,5\times 10^4]\),\(M ...

  3. bootstrap图标乱码问题-解决方案

    楼主在使用bootstrap时,出现了图标乱码问题,经过多次查找,才解决了问题(最后发现真的是很好解决的问题(^^)) 如果出现乱码 请直接在自己写的CSS中重新引入一下font文件中的字体就好了 @ ...

  4. 使用Dreamweaver在一张图片上添加多个热点链接

    所有代码: <html> <head> <meta charset="utf-8"> <title>无标题文档</title& ...

  5. 支付宝小程序日期选择组件datePicker封装

    github 地址 https://github.com/iocool/antminDatePicker 最近在做支付宝小程序(以下简称小程序)开发,发现小程序的日期选择组件很不好用,比如安卓和IOS ...

  6. html5——多媒体(四)

    全屏兼容 box.requestFullscreen(); box.webkitRequestFullScreen(); box.mozRequestFullScreen(); <!DOCTYP ...

  7. JS——样式获取的兼容写法

    样式获取 普通获取属性方式div.style.width或者div.style["width"]无法获取内嵌和外链式,只能获取行内式 window.getComputedStyle ...

  8. [Windows Server 2012] Filezilla安全加固方法

    ★ 欢迎来到[护卫神·V课堂],网站地址:http://v.huweishen.com ★ 护卫神·V课堂 是护卫神旗下专业提供服务器教学视频的网站,每周更新视频. ★ 本节我们将带领大家:FileZ ...

  9. Java 基础入门随笔(1) JavaSE版——java语言三种技术架构

    1.java语言的三种技术架构: J2SE(java 2 Platform Standard Edition):标准版,是为开发普通桌面和商务应用程序提供的解决方案.该技术体系是其他两者的基础,可以完 ...

  10. PHP 设计模式--基础

    设计模式的宗旨就是:重用. 在面向对象中,类是用于生成对象的代码模版,而设计模式是用于解决共性问题的代码模版. 遵循这样的模板,我们可以设快速地设计出优秀的代码. 注意,设计模式只是模板,不是具体的代 ...