hdu3397 Sequence operation 线段树
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+;
struct node {
/// l,r表示当前结点区间范围[l,r]
int l, r;
/// val=0时为全0标志,表示区间[l,r]的值全为0
/// val=1时为全1标志,表示区间[l,r]的值全为1
/// val=-1时则代表无操作
/// xor为异或标志,表示区间[l,r]的值取异或操作
int val, Xor;
/// lmax_0表示区间[l,r]从左往右开始连续0的个数
/// rmax_0表示区间[l,r]从右往左开始连续0的个数
/// max_0表示当前区间最大连续0的个数
int lmax_0, rmax_0, max_0, sum_0;
int lmax_1, rmax_1, max_1, sum_1;
/// 得到当前区间长度
int len() { return r-l+; } /// 更新操作,val_代表01操作,xor_代表异或操作
void change(int val_, int Xor_) {
/// [l,r]全置为0
if (val_ == ) {
lmax_0 = rmax_0 = max_0 = sum_0 = len();
lmax_1 = rmax_1 = max_1 = sum_1 = ;
val = , Xor = ;
}
/// [l,r]全置为1
else if (val_ == ) {
lmax_0 = rmax_0 = max_0 = sum_0 = ;
lmax_1 = rmax_1 = max_1 = sum_1 = len();
val = , Xor = ;
}
/// [l,r]全异或
if (Xor_ == ) {
swap(lmax_0,lmax_1); swap(rmax_0,rmax_1);
swap(max_0,max_1); swap(sum_0,sum_1);
Xor ^= ;
}
}
}tree[maxn*];
int a[maxn];
void pushup(node &fa, node &ls, node &rs) {
/// 父节点的左边最长0串=左子树的左边最长0串
fa.lmax_0 = ls.lmax_0, fa.rmax_0 = rs.rmax_0;
fa.lmax_1 = ls.lmax_1, fa.rmax_1 = rs.rmax_1;
/// 父节点0的数量=左子树0的数量+右子树0的数量
fa.sum_0 = ls.sum_0+rs.sum_0;
fa.sum_1 = ls.sum_1+rs.sum_1;
/// 父节点最大连续0串等于左右子树里面中最大连续0串的最大值
/// 或者是左子树从右开始的0串+右子树从左开始的0串之和
fa.max_0 = max(max(ls.max_0,rs.max_0), ls.rmax_0+rs.lmax_0);
fa.max_1 = max(max(ls.max_1,rs.max_1), ls.rmax_1+rs.lmax_1); /// 如果左子树整串都为0串
if (ls.len() == ls.lmax_0) fa.lmax_0 += rs.lmax_0;
if (ls.len() == ls.lmax_1) fa.lmax_1 += rs.lmax_1;
if (rs.len() == rs.rmax_0) fa.rmax_0 += ls.rmax_0;
if (rs.len() == rs.rmax_1) fa.rmax_1 += ls.rmax_1;
}
void pushdown(int rt) {
if (tree[rt].val != - || tree[rt].Xor) {
tree[rt*].change(tree[rt].val,tree[rt].Xor);
tree[rt*+].change(tree[rt].val,tree[rt].Xor);
tree[rt].val = -, tree[rt].Xor = ;
}
}
void build(int rt, int l, int r) {
/// 结点初始化
tree[rt].l = l, tree[rt].r = r;
tree[rt].lmax_0 = tree[rt].rmax_0 = ;
tree[rt].lmax_1 = tree[rt].rmax_1 = ;
tree[rt].max_0 = tree[rt].max_1 = ;
tree[rt].sum_0 = tree[rt].sum_1 = ;
tree[rt].Xor = , tree[rt].val = -;
/// 如果是叶子结点
if (l == r) {
tree[rt].change(a[l],);
return;
}
int mid = (l+r)/;
build(rt*,l,mid);
build(rt*+,mid+,r);
pushup(tree[rt],tree[rt*],tree[rt*+]);
}
void update(int rt, int l, int r, int op) {
int L = tree[rt].l, R = tree[rt].r;
if (l <= L && R <= r) {
/// 根据op执行不同操作
if (op == || op == ) tree[rt].change(op,);
else if (op == ) tree[rt].change(-,);
return;
}
pushdown(rt);
int mid = (L+R)/;
if (mid >= l) update(rt*,l,r,op);
if (mid < r) update(rt*+,l,r,op);
pushup(tree[rt],tree[rt*],tree[rt*+]);
}
int query(int rt, int l, int r, int op) {
int L = tree[rt].l, R = tree[rt].r;
if (l <= L && R <= r) {
if (op == ) return tree[rt].sum_1;
else if (op == ) return tree[rt].max_1;
}
int mid = (L+R)/;
pushdown(rt);
if (r <= mid) return query(rt*,l,r,op);
else if (l > mid) return query(rt*+,l,r,op);
else {
int max1 = query(rt*,l,r,op);
int max2 = query(rt*+,l,r,op);
if (op == ) return max1+max2;
int max3 = min(tree[rt*].r-l+,tree[rt*].rmax_1)+min(r-tree[rt*+].l+,tree[rt*+].lmax_1);
return max(max(max1,max2),max3);
}
}
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--) {
int op, a, b;
scanf("%d%d%d",&op,&a,&b);
if (op == || op == || op == ) update(,a,b,op);
else printf("%d\n",query(,a,b,op));
}
}
return ;
}
hdu3397 Sequence operation 线段树的更多相关文章
- hdu-3397 Sequence operation 线段树多种标记
题目链接: 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- ...
- Sequence operation(线段树区间多种操作)
Sequence operation Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- 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 线段树 区间更新 区间合并
题意: 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 ...
- HDU 4893 Wow! Such Sequence! (线段树)
Wow! Such Sequence! 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4893 Description Recently, Doge ...
- HDU 5828 Rikka with Sequence (线段树)
Rikka with Sequence 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5828 Description As we know, Rik ...
- Codeforces Round #250 (Div. 1) D. The Child and Sequence(线段树)
D. The Child and Sequence time limit per test 4 seconds memory limit per test 256 megabytes input st ...
- Codeforces Round #350 (Div. 2) E. Correct Bracket Sequence Editor 线段树模拟
E. Correct Bracket Sequence Editor Recently Polycarp started to develop a text editor that works o ...
随机推荐
- 一款被大厂选用的 Hexo 博客主题
首先这是一篇自吹自擂的文章,主题是由多位非前端程序员共同开发,目前经过一年半的迭代已经到达 v1.8.0 版本,并且获得大量认可,甚至某大厂员工已经选用作为内部博客,因此我决定写这篇文章向更多人安利它 ...
- 【linux题目】第二关
1.创建目录/data/oldboy,并且在该目录下创建文件oldboy.txt,然后在文件oldboy.txt里写入内容”inet addr:10.0.0.8 Bcast:10.0.0.255 Ma ...
- centos 编码问题 编码转换 cd到对应目录 执行 中文解压
2019独角兽企业重金招聘Python工程师标准>>> **unzip -O CP936 xxx.zip (用GBK, GB18030也可以)** find -type f -nam ...
- 由JS数组去重说起
一.问题描述: var array=[1,45,3,1,4,67,45],请编写一个函数reDup来去掉其中的重复项,即 reDup(array); console.log(array);//[1,4 ...
- Muduo网络库实战(一):安装和配置
1. 参考资料 <Muduo_网络库使用手册> 2. 实战记录 1) muduo依赖项安装 centos安装cmake命令:# yum install cmake centos安装libb ...
- 无向图求割(找桥)tarjan
本博客参考了李煜东的<算法竞赛进阶指南>,大家要是觉得这篇文章写的不错请大家支持正版.豆瓣图书 我在之前的博客中讲解了搜索序时间戳,这次我们讲讲追溯值的概念. 追溯值: 设subtree( ...
- PHP命令执行学习总结
前言 最近学习了PHP命令执行,内容比较多,把自己学到的总结下来,加深理解,水平有限,欢迎大佬斧正. 什么是PHP命令注入攻击? Command Injection,即命令注入攻击,是指由于Web应用 ...
- Flutter 打包Android APK 笔记与事项
获取一个KEY 首先要获取 你的 打包应用的一个 key ,这一步其实和 在AndroidStudio 上打包 APK 一样,都是要注册一个本地的 key,key 其实也就是 jks文件啦. 如果已经 ...
- Java 创建并应用PPT幻灯片母版
幻灯片母版,可在幻灯片中预先存储设计模板信息,包括字形.占位符大小或位置.背景设计和配色方案等:对设定好的母版可应用于所有幻灯片,也可设计多个不同母版应用于不同幻灯片.下面通过Java代码示例介绍如何 ...
- msf的rpc和json-rpc,我该选择哪个?
msf的rpc有两种调用方式,那么我们应该调用哪一个呢? 其中restful接口暂且不谈,这个rest api其实是简单对接了一下msf的后端数据库,这个自己也能读数据库来做,这个以后有时间再谈 首先 ...