题意:

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. fcntl详解

    功能描述:根据文件描述词来操作文件的特性. #include <unistd.h>#include <fcntl.h> int fcntl(int fd, int cmd);  ...

  2. 8.4 parted:磁盘分区工具

    parted     对于小于2TB的磁盘可以用fdisk和parted命令进行分区,这种情况一般采用flisk命令,但对于大于2TB的磁盘则只能用parted分区,且需要将磁盘转换为GPT格式. p ...

  3. STM32SD卡 (U盘)IAP升级

    http://www.openedv.com/posts/list/65104.htm

  4. 看完这篇还不懂 MySQL 主从复制,可以回家躺平了~

    大家好,我是小羽. 我们在平时工作中,使用最多的数据库就是 MySQL 了,随着业务的增加,如果单单靠一台服务器的话,负载过重,就容易造成宕机. 这样我们保存在 MySQL 数据库的数据就会丢失,那么 ...

  5. 火币HBAI量化币圈唯一免费量化炒币机器人

    量化交易是一种投资方法.以先进的数学模型替代人为的主观判断,利用计算机技术从庞大的历史数据中海选能带来超额收益的多种"大概率"事件以制定策略,极大地减少了投资者情绪波动的影响,避免 ...

  6. python基础课程讲解

    day01: 编程语言的介绍: 一 1.什么是编程?(****) 两个环节: 1.把做事的思维逻辑给想清楚了 2.用计算机能听懂的语言也就是编程语言把做事的步骤给翻译下来 2.为什么要编程? 人要奴役 ...

  7. AtCoder Regular Contest 121 D - 1 or 2

    题目链接:点我点我 Problem Statement Snuke has a blackboard and NN candies. The tastiness of the ii-th candy ...

  8. 『言善信』Fiddler工具 — 4、Fiddler面布局详解【工具栏】

    目录 (一)工具栏详细介绍 1.第一组工具: 2.第二组工具: 3.第三组工具: 4.第四组工具: (二)工具栏使用说明 1.Fiddler修改代理端口: 2.过滤Tunnel to...443请求链 ...

  9. 07.ElementUI 2.X 源码学习:源码剖析之工程化(二)

    0x.00 前言 项目工程化系列文章链接如下,推荐按照顺序阅读文章 . 1️⃣ 源码剖析之工程化(一):项目概览.package.json.npm script 2️⃣ 源码剖析之工程化(二):项目构 ...

  10. sql批量插入缓慢

    1.有一个普通的表t_asset,只有2个字段id,ip 没有索引 2.当用insert into t_asset(id,ip) values(?,?),(?,?) 1200多条记录时,发现竟然用了3 ...