题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=3397

题目大意:

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的长度

解题思路:

线段树多种标记。

需要处理的东西比较多:

做题的时候发现一个问题:

我的宏定义Max不可以用于函数,尤其是递归函数,这样会使得同一函数重复调用好几遍,递归函数的话更会超时。

 #include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);//不可再使用scanf printf
#define Max(a, b) ((a) > (b) ? (a) : (b))//禁用于函数,会超时
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Mem(a) memset(a, 0, sizeof(a))
#define Dis(x, y, x1, y1) ((x - x1) * (x - x1) + (y - y1) * (y - y1))
#define MID(l, r) ((l) + ((r) - (l)) / 2)
#define lson ((o)<<1)
#define rson ((o)<<1|1)
#pragma comment(linker, "/STACK:102400000,102400000")//栈外挂
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while (ch<''||ch>''){if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
} typedef long long ll;
const int maxn = + ;
const int MOD = ;//const引用更快,宏定义也更快 struct node
{
int l, r;//左右区间
int ls0, rs0, ms0;//左连续的0,右连续的0,区间最大连续的0
int ls1, rs1, ms1;//左连续的1,右连续的1,区间最大连续的1
int sum0, sum1;//区间0 1数目
int lazy, Xor;//懒惰标记和异或标记
}tree[maxn << ];
int a[maxn];
void pushup(int o)
{
if(tree[o].l == tree[o].r)return;//叶子节点直接返回
//根据子节点的信息,更新父节点信息 //更新0:
int lc = lson, rc = rson;
tree[o].ls0 = tree[lc].ls0;
tree[o].rs0 = tree[rc].rs0;
if(tree[lc].ls0 == tree[lc].r - tree[lc].l + )
tree[o].ls0 += tree[rc].ls0;//左节点左连续的0为区间长度 那么根节点左连续的0需要再加上右节点左连续的0
if(tree[rc].rs0 == tree[rc].r - tree[rc].l + )
tree[o].rs0 += tree[lc].rs0;
tree[o].ms0 = Max(Max(tree[lc].ms0, tree[rc].ms0), tree[lc].rs0 + tree[rc].ls0);//最大连续0 = Max(左节点最大连续0, 右节点最大连续0,中间最大连续0)
tree[o].sum0 = tree[lc].sum0 + tree[rc].sum0;
//更新1
tree[o].ls1 = tree[lc].ls1;
tree[o].rs1 = tree[rc].rs1;
if(tree[lc].ls1 == tree[lc].r - tree[lc].l + )
tree[o].ls1 += tree[rc].ls1;//左节点左连续的0为区间长度 那么根节点左连续的0需要再加上右节点左连续的0
if(tree[rc].rs1 == tree[rc].r - tree[rc].l + )
tree[o].rs1 += tree[lc].rs1;
tree[o].ms1 = Max(Max(tree[lc].ms1, tree[rc].ms1), tree[lc].rs1 + tree[rc].ls1);//最大连续0 = Max(左节点最大连续0, 右节点最大连续0,中间最大连续0)
tree[o].sum1 = tree[lc].sum1 + tree[rc].sum1;
}
void XOR(int o)
{
swap(tree[o].ls0, tree[o].ls1);
swap(tree[o].rs0, tree[o].rs1);
swap(tree[o].ms0, tree[o].ms1);
swap(tree[o].sum0, tree[o].sum1);
}
void pushdown(int o)//标记下传
{
if(tree[o].l == tree[o].r)return;
if(tree[o].lazy != -)//区间覆盖0或者1
{
int lc = lson, rc = rson, len = tree[o].r - tree[o].l + ;
tree[lc].lazy = tree[rc].lazy = tree[o].lazy;
tree[lc].Xor = tree[rc].Xor = ; //左节点长度为(len+1) / 2 右节点长度为len/2
//左
tree[lc].ls0 = tree[lc].rs0 = tree[lc].ms0 = tree[o].lazy ? : (len + ) / ;
tree[lc].ls1 = tree[lc].rs1 = tree[lc].ms1 = tree[o].lazy ? (len + ) / : ;
tree[lc].sum0 = tree[o].lazy ? : (len + ) / ;
tree[lc].sum1 = tree[o].lazy ? (len + ) / : ;
//右
tree[rc].ls0 = tree[rc].rs0 = tree[rc].ms0 = tree[o].lazy ? : (len) / ;
tree[rc].ls1 = tree[rc].rs1 = tree[rc].ms1 = tree[o].lazy ? (len) / : ;
tree[rc].sum0 = tree[o].lazy ? : (len) / ;
tree[rc].sum1 = tree[o].lazy ? (len) / : ; tree[o].lazy = -;//清除标记
}
if(tree[o].Xor)
{
tree[o].Xor = ;
tree[lson].Xor ^= ;
tree[rson].Xor ^= ;
XOR(lson), XOR(rson);
}
}
void build(int o, int l, int r)
{
tree[o].l = l, tree[o].r = r, tree[o].lazy = -, tree[o].Xor = ;
if(l == r)
{
tree[o].ls0 = tree[o].rs0 = tree[o].ms0 = (a[l] == );
tree[o].ls1 = tree[o].rs1 = tree[o].ms1 = (a[l] == );
tree[o].sum1 = (a[l] == );
tree[o].sum0 = (a[l] == );
return;
}
int m = MID(l, r);
build(lson, l, m);
build(rson, m + , r);
pushup(o);
}
int flag;//标记类型
int ql, qr;
void update(int o)
{
pushdown(o);
if(ql <= tree[o].l && qr >= tree[o].r)
{
if(flag == )
{
tree[o].Xor = ;
XOR(o);
}
else
{
int len = tree[o].r - tree[o].l + ;
tree[o].lazy = flag;
tree[o].ls0 = tree[o].rs0 = tree[o].ms0 = flag ? : len;
tree[o].ls1 = tree[o].rs1 = tree[o].ms1 = flag ? len : ;
tree[o].sum0 = flag ? : len;
tree[o].sum1 = flag ? len : ;
}
}
else
{
int m = MID(tree[o].l, tree[o].r);
if(ql <= m)update(lson);
if(qr > m)update(rson);
pushup(o);
}
} int query(int o)
{
pushdown(o);
if(ql <= tree[o].l && qr >= tree[o].r)
{
if(flag == )return tree[o].sum1;
else return tree[o].ms1;
}
else
{
if(qr <= tree[lson].r)return query(lson);
if(ql >= tree[rson].l)return query(rson);
if(flag == )return query(lson) + query(rson);
int ans1 = Min(tree[lson].rs1, tree[lson].r - ql + ) + Min(tree[rson].ls1, qr - tree[rson].l + );
int ans2 = max(query(lson), query(rson));//用宏定义会超时,因为一直在递归
return Max(ans1, ans2);
}
} int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int n, m;
scanf("%d%d", &n, &m);
for(int i = ; i <= n; i++)scanf("%d", &a[i]);
build(, , n);
while(m--)
{
scanf("%d%d%d", &flag, &ql, &qr);
ql++, qr++;
if(flag < )update();
else printf("%d\n", query());
}
}
return ;
}

hdu-3397 Sequence operation 线段树多种标记的更多相关文章

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

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

  2. hdu 3397 Sequence operation 线段树

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

  3. 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 ...

  4. 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变 ...

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

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

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

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

  7. 【线段树】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 ...

  8. Sequence operation(线段树区间多种操作)

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

  9. hdu3397 Sequence operation 线段树

    hdu3397 Sequence operation #include <bits/stdc++.h> using namespace std; ; struct node { /// l ...

随机推荐

  1. 移动端的touchstart,touchmove,touchend事件中的获取当前touch位置

    前提:touchstart,touchmove,touchend这三个事件可以通过原生和jq绑定. 原生:document.querySelector("#aa").addEven ...

  2. js 写日期选择器

    <html> <head> <title>Js日期选择器并自动加入到输入框中</title> <meta http-equiv="con ...

  3. g2o error2

    ./pose_estimation_3d2d: error while loading shared libraries: libg2o_core.so: cannot open shared obj ...

  4. linux下elasticsearch集成mongodb详细教程

    由于公司业务需要,要用elasticsearch做索引库实现搜索功能,历尽千辛万苦,最后总算把mongodb和elasticsearch集成成功 1.搭建mongodb集群 参考https://www ...

  5. 前端(十二):react-redux实现逻辑

    一.context实现数据传递 在react中,props和state都可以设置数据.不同的是,props借助组件属性传递数据但不可以渲染组件,它相对来说是“静态的”:state可以监听事件来修改数据 ...

  6. 2.springioc实例化bean的三个方法

    1.构造器 也就是在上一篇讲的那个例子,调用默认的无参构造函数 2.静态工厂方法 1)创建需要执行的方法的类 public class HelloWorld { public HelloWorld() ...

  7. Tomcat的下载安装及使用

    macOS Sierra Version 10.13.2 环境下Tomcat的下载与安装以及InterlliJ IDEA 2017.2 环境下配置Tomcat 与创建Web项目 一.Tomcat的下载 ...

  8. python学习之老男孩python全栈第九期_day019知识点总结——collections模块、时间模块、random模块、os模块、sys模块

    一. collections模块 在内置数据类型(dict.list.set.tuple)的基础上,collections模块还提供了几个额外的数据类型:namedtuple.deque.Counte ...

  9. 神奇的AC

  10. 使用WampServer搭建本地PHP环境,绑定域名,配置伪静态

    倡萌之前介绍过 USBWebserver 快速搭建本地PHP环境 ,推荐USBWebserver的原因在于它是绿色的,不需要安装,想使用就手动运行下即可.但是 USBWebserver 也有自身的弱点 ...