/*
一开始维护了两个标记 开了两个数组
想的是 可能当前两种操作都要做
但是太复杂了 不好处理
其实 当前要做的标记可以只有一个 我们在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. dropdownlist显示树形结构

    /// <summary> /// 递归 /// </summary> /// <param name="deplist"></param ...

  2. Android sensor 系统框架 (一)

    这几天深入学习了Android sensor框架,以此博客记录和分享分析过程,其中难免会有错误的地方,欢迎指出! 这里主要分析KERNEL->HAL->JNI这3层的流程.主要从以下几方面 ...

  3. [Windows Server 2008] 手工创建安全网站

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

  4. 仿iphone动态萤火虫锁屏应用安卓源码

    该源码是仿iphone动态萤火虫锁屏应用源码,源码SkyLock,这也是最近弄了一款锁屏,苦于市场百般阻拦与锁屏应用数量实在太多,于是将它拿出来开源:废话不多说,希望大家能够希望,更多说明请看下面的吧 ...

  5. Concurrency and Application Design

    Concurrency and Application Design In the early days of computing, the maximum amount of work per un ...

  6. C# null

    var t0est = Convert.ToString(""+null);//结果"" var t1est = ("" + null).T ...

  7. PHP 之websocket实现聊天室功能

    一.功能界面 具体的详细代码:https://github.com/yangsphp/websocket-master/tree/master 二.具体代码实现 1.前端代码如下 <!DOCTY ...

  8. scss基础

    1.变量$ 全局 局部 .div{ $color:yellow; } 2.类似函数@mixin border-radius($radius) { }引用:@include border-radius( ...

  9. CPU 指令集(Instruction Set Architecture, ISA)

    本文摘自网络 概念 指令集是存储在CPU内部,对CPU运算进行指导和优化的硬程序,用来引导CPU进行加减运算和控制计算机操作系统的一系列指令集合.拥有这些指令集,CPU就可以更高效地运行.系统所下达的 ...

  10. Linux - VMware和Centos安装

    目录 Linux - VMware和Centos安装 选择性 下载centos系统ISO镜像 安装虚拟机VMware虚拟机 1. 准备vmware软件 2. 解压软件包, 当前选择vm12 3. vm ...