题意:

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

这题看题目就很裸,综合了区间更新,区间合并

我一开始把更新操作全放一个变量,但是在push_down的时候很麻烦,情况很多,容易漏,后来改成下面的

更新的操作可以分为两类,一个是置值(stv),一个是互换(swp)。如果stv!=-1,则更新儿子节点的stv,并将儿子的swp=0。如果swp=1,这里要注意一点,不是把儿子的swp赋值为1,而是与1异或!!!因为如果儿子的swp本为1,再互换一次,两个互换就相当于值没有变了。

注意下细节就行了

#include <bits/stdc++.h>
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
using namespace std; const int MAXN = 111111; struct Node
{
int num1, stv, swp;
int mx0, lmx0, rmx0;
int mx1, lmx1, rmx1;
} tr[MAXN<<2]; void changeto(int rt, int to,int len)
{
tr[rt].mx0 = tr[rt].lmx0 = tr[rt].rmx0 = to? 0 : len;
tr[rt].mx1 = tr[rt].lmx1 = tr[rt].rmx1 = tr[rt].num1 = to? len : 0;
} void exchange(int rt, int len)
{
tr[rt].num1 = len - tr[rt].num1;
swap(tr[rt].mx0, tr[rt].mx1);
swap(tr[rt].lmx0, tr[rt].lmx1);
swap(tr[rt].rmx0, tr[rt].rmx1);
} void push_down(int rt, int len)
{
if(tr[rt].stv != -1)
{
tr[rt<<1].stv = tr[rt<<1|1].stv = tr[rt].stv;
tr[rt<<1].swp = tr[rt<<1|1].swp = 0;
changeto(rt<<1, tr[rt].stv, len-(len>>1));
changeto(rt<<1|1, tr[rt].stv, len>>1);
tr[rt].stv = -1;
}
if(tr[rt].swp == 1)
{
tr[rt<<1].swp ^= 1;
tr[rt<<1|1].swp ^= 1;
exchange(rt<<1, len-(len>>1));
exchange(rt<<1|1, len>>1);
tr[rt].swp = 0;
}
} void push_up(int rt, int len)
{
tr[rt].num1 = tr[rt<<1].num1 + tr[rt<<1|1].num1; tr[rt].lmx0 = tr[rt<<1].lmx0;
tr[rt].rmx0 = tr[rt<<1|1].rmx0;
if(tr[rt].lmx0 == len - (len >> 1)) tr[rt].lmx0 += tr[rt<<1|1].lmx0;
if(tr[rt].rmx0 == len >> 1) tr[rt].rmx0 += tr[rt<<1].rmx0;
tr[rt].mx0 = max(tr[rt<<1].rmx0 + tr[rt<<1|1].lmx0, max(tr[rt<<1].mx0, tr[rt<<1|1].mx0)); tr[rt].lmx1 = tr[rt<<1].lmx1;
tr[rt].rmx1 = tr[rt<<1|1].rmx1;
if(tr[rt].lmx1 == len - (len >> 1)) tr[rt].lmx1 += tr[rt<<1|1].lmx1;
if(tr[rt].rmx1 == len >> 1) tr[rt].rmx1 += tr[rt<<1].rmx1;
tr[rt].mx1 = max(tr[rt<<1].rmx1 + tr[rt<<1|1].lmx1, max(tr[rt<<1].mx1, tr[rt<<1|1].mx1));
} void build(int l, int r, int rt)
{
tr[rt].stv = -1;
tr[rt].swp = 0;
if(l == r)
{
scanf("%d", &tr[rt].num1);
tr[rt].mx0 = tr[rt].lmx0 = tr[rt].rmx0 = tr[rt].num1 ^ 1;
tr[rt].mx1 = tr[rt].lmx1 = tr[rt].rmx1 = tr[rt].num1;
return;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
push_up(rt, r-l+1);
} void update(int L, int R, int op, int l, int r, int rt)
{
if(L <= l && r <= R)
{
if(op == 0 || op == 1)
{
changeto(rt, op, r-l+1);
tr[rt].stv = op;
tr[rt].swp = 0;
}
else
{
exchange(rt, r-l+1);
tr[rt].swp ^= 1;
}
return;
}
push_down(rt, r-l+1);
int m = (l + r) >> 1;
if(m >= L) update(L, R, op, lson);
if(m < R) update(L, R, op, rson);
push_up(rt, r-l+1);
} int query1(int L, int R, int l, int r, int rt)
{
if(L <= l && r <= R) return tr[rt].num1;
push_down(rt, r-l+1);
int m = (l + r) >> 1;
int ret = 0;
if(m >= L) ret += query1(L, R, lson);
if(m < R) ret += query1(L, R, rson);
return ret;
} int query2(int L, int R, int l, int r, int rt)
{
if(L <= l && r <= R) return tr[rt].mx1;
push_down(rt, r-l+1);
int m = (l + r) >> 1;
int ret = 0;
if(m >= L) ret = max(ret, query2(L, R, lson));
if(m < R) ret = max(ret, query2(L, R, rson));
ret = max(ret, min(tr[rt<<1].rmx1, m-L+1) + min(tr[rt<<1|1].lmx1, R-m));
return ret;
} int main()
{
// freopen("in.txt", "r", stdin);
int T;
scanf("%d", &T);
while(T--)
{
int n, m;
scanf("%d%d", &n, &m);
build(0, n-1, 1);
while(m--)
{
int op, x, y;
scanf("%d%d%d", &op, &x, &y);
if(op <= 2) update(x, y, op, 0, n-1, 1);
else if(op == 3) printf("%d\n", query1(x, y, 0, n-1, 1));
else printf("%d\n", query2(x, y, 0, n-1, 1));
}
}
return 0;
}

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(线段树)

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

  4. HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对)

    HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对) 题意分析 给出n个数的序列,a1,a2,a3--an,ai∈[0,n-1],求环序列中逆序对 ...

  5. hdu 1166线段树 单点更新 区间求和

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  6. POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)

    POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和) 题意分析 卡卡屋前有一株苹果树,每年秋天,树上长了许多苹果.卡卡很喜欢苹果.树上有N个节点,卡卡给他们编号1到N,根 ...

  7. POJ.2299 Ultra-QuickSort (线段树 单点更新 区间求和 逆序对 离散化)

    POJ.2299 Ultra-QuickSort (线段树 单点更新 区间求和 逆序对 离散化) 题意分析 前置技能 线段树求逆序对 离散化 线段树求逆序对已经说过了,具体方法请看这里 离散化 有些数 ...

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

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

  9. HDU 3577Fast Arrangement(线段树模板之区间增减更新 区间求和查询)

    Fast Arrangement Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

随机推荐

  1. [转载]层叠与并排win10

    三. 层叠与并排 如果要排列的窗口超过4个,分屏就显得有些不够用了,这时不妨试一试最传统的窗口排列法.具体方法是,右击任务栏空白处,然后选择"层叠窗口"."并排显示窗口& ...

  2. (代替人类)很多操作都在Settings里面。 5.安装第三方库

    2020-02-01 pycharm 使用教程 LingSmart关注 0.0842020.02.07 15:08:50字数 1,394阅读 680 实在无聊,就来学习吧.学习pycharm的使用教程 ...

  3. VMware虚拟机性能优化

    一.ESX及vCenter服务器的优化 检查ESX物理服务器是否在兼容列表中,特别是BIOS的版本是否符合ESX版本的要求 开启ESX物理服务器硬件虚拟化技术VT-X,AMD-V 关闭BIOS中的英特 ...

  4. Debian 9.4 多网卡链路聚合bond配置

    Debian 9.4 多网卡链路聚合bond配置 安装ifenslave ifenslave 的作用是网卡的负载均衡 root@debian:~# apt-get install ifenslave ...

  5. BRAM 和 DRAM 区别

    转载: BRAM和DRAM的区别 Xilinx的FPGA开发板可以直接调用RAM,其中包括了BRAM和DRAM.经过网上查找资料发现,这两者的区别在于: 选择distributed memory ge ...

  6. Apache Flink 1.12.0 正式发布,DataSet API 将被弃用,真正的流批一体

    Apache Flink 1.12.0 正式发布 Apache Flink 社区很荣幸地宣布 Flink 1.12.0 版本正式发布!近 300 位贡献者参与了 Flink 1.12.0 的开发,提交 ...

  7. SpringBoot2 单元测试类的报错问题

    问题描述 执行 SpringBoot2 测试时报错,提示找不到 SsmApplicationTests 主类 原因分析 Junit5 升级了框架没有兼容 问题解决 <!--测试模块--> ...

  8. 惊奇发现KEIL也可以C++编译了

    在Github上面浏览下载的一个工程,可以用KEIL打开,但是我竟然找不到mian函数.找了一圈发现是用到了面向对象的编程方法,那就必须支持C++,他怎么实现的呢? 看配置工程:明显的一个不一样 -- ...

  9. 一次线上事故,让我对MySql的时间戳存char(10)还是int(10)有了全新的认识

    美好的周五 周五的早晨,一切都是那么美好. 然鹅,10点多的时候,运营小哥哥突然告诉我后台打不开了,我怀着一颗"有什么大不了的,估计又是(S)(B)不会连wifi"的心情,自信的打 ...

  10. 计划任务 at & crond tbc

    一次性任务 at 工具 由包 at 提供 依赖与atd服务,需要启动才能实现at任务 at队列存放在/var/spool/at目录中 执行任务时PATH变量的值和当前定义任务的用户身份一致 作业执行命 ...