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]中的最长连续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 线段树 区间更新 区间合并的更多相关文章
- hdu 3397 Sequence operation (线段树 区间合并 多重标记)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=3397 题意: 给你一串01串,有5种操作 0. 区间全部变为0 1.区间全部变为1 2.区间异或 3.询问 ...
- hdu 3397 Sequence operation 线段树
题目链接 给出n个数, 每个数是0或1, 给5种操作, 区间变为1, 区间变为0, 区间0,1翻转, 询问区间内1的个数, 询问区间内最长连续1的个数. 需要将数组开成二维的, 然后区间0, 1翻转只 ...
- 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变 ...
- HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对)
HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对) 题意分析 给出n个数的序列,a1,a2,a3--an,ai∈[0,n-1],求环序列中逆序对 ...
- hdu 1166线段树 单点更新 区间求和
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)
POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和) 题意分析 卡卡屋前有一株苹果树,每年秋天,树上长了许多苹果.卡卡很喜欢苹果.树上有N个节点,卡卡给他们编号1到N,根 ...
- POJ.2299 Ultra-QuickSort (线段树 单点更新 区间求和 逆序对 离散化)
POJ.2299 Ultra-QuickSort (线段树 单点更新 区间求和 逆序对 离散化) 题意分析 前置技能 线段树求逆序对 离散化 线段树求逆序对已经说过了,具体方法请看这里 离散化 有些数 ...
- hdu 3397 Sequence operation(很有意思的线段树题)
Sequence operation Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- HDU 3577Fast Arrangement(线段树模板之区间增减更新 区间求和查询)
Fast Arrangement Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) ...
随机推荐
- 本文介绍使用windows系统自带的远程桌面mstsc连接Centos 7.x远程桌面的基本方法。
本文介绍使用windows系统自带的远程桌面mstsc连接Centos 7.x远程桌面的基本方法. 一.前言 我希望用windows远程访问centos图形界面.xmanager连接centos远程桌 ...
- OpenStack挂载ISO镜像解决
OpenStack挂载ISO镜像解决 Summary 本次在OpenStack平台上进行,基于kvm,挂载iso镜像到OpenStack虚拟机中. 1.针对linux: 上传所需要挂载的iso镜像(必 ...
- 进程-信号相关 函数-(转自wblyuyang)
Linux 中的进程: 程序时一个预定义的指令序列,用来完成一个特定的任务. C 编译器可以把每个源文件翻译成一个目标文件,链接器将所有的目标文件与一些必要的库链接在一起,产生一个可执行文件.当程序被 ...
- Linux 性能监控工具
- Ajax向服务器端发送请求
Ajax向服务器端发送请求 Ajax的应用场景 页面上拉加载更多数据 列表数据无刷新分页 表单项离开焦点数据验证 搜索框提示文字下拉列表 Ajax运行原理 Ajax 相当于浏览器发送请求与接收响应的代 ...
- python rpc 的实现
所谓RPC,是远程过程调用(Remote Procedure Call)的简写,网上解释很多,简单来说,就是在当前进程调用其他进程的函数时,体验就像是调用本地写的函数一般.本文实现的是在本地调用远端的 ...
- Jmeter(四十九) - 从入门到精通高级篇 - jmeter使用监视器结果监控tomcat性能(详解教程)
1.简介 上一篇宏哥讲解了利用jmeter的插件来监控服务器资源,这一篇讲解分享如何使用jmeter的监视器结果监控tomcat性能. 2.准备工作 文章标题中提到jmeter和tomcat,那么只需 ...
- 吐血整理!Python常用第三方库,码住!!!
Python作为一种编程语言近年来越来越受欢迎,它为什么这么火? 其中一个重要原因就是因为Python的库丰富--Python语言提供超过15万个第三方库,Python库之间广泛联系.逐层封装.几 ...
- GO学习-(25) Go操作Redis实战
Go操作Redis实战 安装Redis客户端 Go语言中使用第三方库https://github.com/go-redis/redis连接Redis数据库并进行操作.使用以下命令下载并安装: go ...
- Deep Learning部署TVM Golang运行时Runtime
Deep Learning部署TVM Golang运行时Runtime 介绍 TVM是一个开放式深度学习编译器堆栈,用于编译从不同框架到CPU,GPU或专用加速器的各种深度学习模型.TVM支持来自Te ...