HDU 3397 Sequence operation 多标记线段树
/*
一开始维护了两个标记 开了两个数组
想的是 可能当前两种操作都要做
但是太复杂了 不好处理
其实 当前要做的标记可以只有一个 我们在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 多标记线段树的更多相关文章
- 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变 ...
- hdu 3397 Sequence operation (线段树 区间合并 多重标记)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=3397 题意: 给你一串01串,有5种操作 0. 区间全部变为0 1.区间全部变为1 2.区间异或 3.询问 ...
- hdu 3397 Sequence operation(线段树:区间更新)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3397 题意:给你一个长度为n的0,1序列,支持下列五种操作, 操作0(0 a b):将a到b这个区间的 ...
- hdu 3397 Sequence operation(很有意思的线段树题)
Sequence operation Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- 【线段树】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 ...
- (简单) HDU 3397 Sequence operation,线段树+区间合并。
Problem Description lxhgww got a sequence contains n characters which are all '0's or '1's. We have ...
- hdu 3397 Sequence operation 线段树
题目链接 给出n个数, 每个数是0或1, 给5种操作, 区间变为1, 区间变为0, 区间0,1翻转, 询问区间内1的个数, 询问区间内最长连续1的个数. 需要将数组开成二维的, 然后区间0, 1翻转只 ...
- HDU 3397"Sequence operation"(线段树区间和并)
传送门 •题意 给你一个仅包含 0 和 1 的序列: 在这个序列上有如下操作: (1)0 a b : 将 [a,b] 区间的数置 0: (2)1 a b : 将 [a,b] 区间的数置 1: (3)2 ...
- 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 ...
随机推荐
- 深拷贝js
JSON 最简单的一个 let obj = {} let newObj = JSON.parse(JSON.stringify(obj)) 弊端:这种方法无法拷贝function函数,undefine ...
- 定制UVM Messages(参考)
UVM的Messages机制有些时候很繁琐,很多时候希望能够在UVM messages的基础上做一些个人化的订制,这里给出来一个找到的例子作为参考. my_macros.sv: `define ...
- 正则表达式提取String子串
最近遇到了一个字符串处理的功能,忽然发现了正则表达式的强大,深深的被她的迷人魅力所吸引,以前只是听说,今天亲眼所见,亲身经历,真的彻底折服. 言归正传:java中String类里面封装了很多字符串处理 ...
- 【译】x86程序员手册10 - 第4章系统架构
1.1.2 Part II -- Systems Programming 系统编程 This part presents those aspects of the architecture that ...
- C#鸡翁百鸡
一个for static void Main(string[] args) { int x, y, z; ; x <= ; x++) { - * x) % == ) { y = ( - * x) ...
- Python 之动态添加属性以及方法
import types class Person(object): def __init__(self, newName, newAge): self.name = newName self.age ...
- Sping bean的作用域
单例(Singleton):在整个应用中,只创建bean的一个实例.(默认) 原型(Prototype):每次注入或者通过Sping应用上下文获取的时候,都会创建一个新的bean. 回话(Sessio ...
- 初学者怎么才能快速学会Python?
提起对Python的印象,除了全能之外恐怕就是简单易学了.很多人都在推荐新手学Python入门,毕竟语法简单.语句简洁,所谓“人生苦短我用Python”绝不是一句空话.不过也不能忽视一点:Python ...
- Xpath语法与lxml库
1. Xpath 1 )什么是XPath? xpath(XML Path Language)是一门在XML和HTML文档中查找信息的语言,可用来在XML和HTML文档中对元素和属性进行遍历. 2) X ...
- Enable ssh root login in Solaris
1. Change the file /etc/ssh/sshd_config with PermitRootLogin yes to replace PermitRootLogin no 2. re ...