题意:

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. Linux 系统优化-workstation实践

    Linux 系统优化 关闭SELinux [root@workstation ~]# sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/seli ...

  2. VIM 三种模式和常用命令

    引言 大数据开发工作中,周围的同事不是用 VIM 就是 Emacs,你要是用 UltraEdit 或 notepad++ 都不好意思跟人家打招呼...什么插件呀.语法高亮呀.拼写检查呀,能给它开的都给 ...

  3. 针对spring mvc的controller内存马-学习和实验

    1 基础 实际上java内存马的注入已经有很多方式了,这里在学习中动手研究并写了一款spring mvc应用的内存马.一般来说实现无文件落地的java内存马注入,通常是利用反序列化漏洞,所以动手写了一 ...

  4. 只需5分钟!一文读懂CSS布局(二) -- flex布局

    目录 简介 基本概念 容器属性 1. flex-direction 测试代码 2. flex-wrap 3. flex-flow 4. justify-content 5. align-items 6 ...

  5. 在.NET 6中使用DateOnly和TimeOnly

    千呼万唤始出来 在.NET 6(preview 4)中引入了两个期待已久的类型,将作为核心库的一部分.DateOnly和TimeOnly允许开发人员表示DateTime的日期或时间部分.这两个类型为值 ...

  6. CRC校验原理简介及C代码实现说明

    1 原理 参考文档:CRC校验 (qq.com) 参考书籍:<计算机网络(第7版)-谢希仁> 1.1 原理简介 CRC是一种检错方法. 在发送端,先把数据划分为组,假定每组k个比特.现假定 ...

  7. redis全解

    Redis全解 1.什么是Redis? Redis本质上是一个Key-Value类型的内存数据库,很像memcached,整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到 ...

  8. Python+Selenium学习笔记9 - 警告框处理

    如下图所示,这种窗口是不能通过前端工具对其进行定位的,这里可以通过switch_to_alert()方法去接受这个弹窗 1 # coding = utf-8 2 3 from selenium imp ...

  9. Spring的controller接受Date类型数据,接受枚举类型数据

    1. Controller接收Date类型的数据 核心使用@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") 来将传递过来的时间字符串 ...

  10. Mybatis基础使用方法

    1.首先在数据库中建立一张表 create table login( name varchar(20) not null, username varchar(20) not null, passwor ...