题目链接:

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. [转]OPEN(SAP) UI5 学习入门系列之一:扫盲与热身(上)

    本文转自:http://www.cnblogs.com/qianmarv/p/4671394.html 1 扫盲 什么是SAP Fiori? 了解SAP UI5必须要从SAP Fiori开始,两者概念 ...

  2. TRUNCATE TABLE 与 DELETE的区别

    delete from aatruncate table aa 区别1.delete from后面可以写条件,truncate不可以2.delete from记录是一条条删的,所删除的每行记录都会进日 ...

  3. java线程总结2--wait/notify(all)/sleep以及中断概念

    上一篇关于线程的博客简单梳理了一下多线程的一些基本概念,今天这篇博客再进行多线程编程中一些核心的方法进行简单的梳理和总结,主要是wait,sleep和notify方法以及中断的概念 一.中断概念. 在 ...

  4. 五、curator recipes之选举主节点Leader Latch

    简介 在分布式计算中,主节点选举是为了把某个进程作为主节点来控制其它节点的过程.在选举结束之前,我们不知道哪个节点会成为主节点.curator对于主节点选举有两种实现方式,本文示例演示Latch的实现 ...

  5. HDU 1875(最小生成树)

    因为是全连接图,所以也可以用最小生成树 这道题给边加了一个限制条件,(10<=x<=1000),所以可能不能全连通,需要判断 #include <cstdio> #includ ...

  6. IDEA使用maven建web项目示例

    运行环境:OSX-10.13.3. IDEA-2017.3.3. maven-3.5.2 步骤1:选择maven-webapp模板新建web项目 步骤2:设置项目GroupId等 需从网上下载相关构件 ...

  7. Java 泛型的使用

    一.泛型的简介1.为什么要使用泛型? 一般使用在集合上,比如现在把一个字符串类型的值放入到集合里面,这个时候,这个值放到集合之后,失去本身的类型,只能是object类型.这时,如果想要对这个值进行类型 ...

  8. Html5 填表 表单(二) input type 各种输入, 各种用户选择,上传等等泛输入用户交互

    <input>        无限制输入     type    限制输入 type = 如下类型     type 后还可以跟一些属性: 如<input type=text max ...

  9. java多线程中的死锁、活锁、饥饿、无锁都是什么鬼?

    死锁.活锁.饥饿是关于多线程是否活跃出现的运行阻塞障碍问题,如果线程出现了这三种情况,即线程不再活跃,不能再正常地执行下去了. 死锁 死锁是多线程中最差的一种情况,多个线程相互占用对方的资源的锁,而又 ...

  10. HTML 5 教程

    HTML5 是下一代的 HTML.有必要再过一遍.看下要点. 具体看  http://www.w3school.com.cn/html5/index.asp    教程 和  HTML5 标签参考手册 ...