HDU 3397 Sequence operation(区间合并 + 区间更新)
题目链接: pid=3397">http://acm.hdu.edu.cn/showproblem.php?pid=3397
题意:给定n个数,由0,1构成。共同拥有5种操作。
每一个操作输入3个数,op,a。b。
- op == 0。将区间[a,b]赋值为0。
- op == 1,将区间[a,b]赋值为1;
- op == 2。将区间[a。b]内的01反转;
- op == 3。查询区间[a。b]中1的个数。
- op == 4,查询区间[a。b]中连续1的最大长度。
思路:区间合并 + 区间更新。
每一个结点存7个数:
- 区间内1的个数c1。
- 从区间左端点開始连续1的最大长度l1。
- 以区间右端点结束连续1的最大长度r1。
- 区间内连续1的最大长度m1。
- 从区间左端点開始连续0的最大长度l0。
- 以区间右端点结束连续0的最大长度r0。
- 区间内连续0的最大长度m0。
记录0的连续是为了反转后统计结果方便。
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <string>
using namespace std;
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
const int N = 1e5 + 10;
const int INF = 0x7f7f7f7f;
struct Node {
int c1;
int l1, r1, m1;
int l0, r0, m0;
Node() {}
Node(int a, int b, int c, int d, int e, int f, int g) {
c1 = a;
l1 = b;
r1 = c;
m1 = d;
l0 = e;
r0 = f;
m0 = g;
}
void reversal(int s) {
c1 = s;
swap(l1, l0);
swap(r1, r0);
swap(m1, m0);
}
};
Node node[N << 2];
int cover[N << 2];
int XOR[N << 2];
void pushup(int rt, int l, int r) {
int m = (l + r) >> 1;
int lenl = m - l + 1;
int lenr = r - m;
node[rt].c1 = node[rt << 1].c1 + node[rt << 1 | 1].c1;
if (node[rt << 1].l1 == lenl)
node[rt].l1 = node[rt << 1].l1 + node[rt << 1 | 1].l1;
else
node[rt].l1 = node[rt << 1].l1;
if (node[rt << 1 | 1].r1 == lenr)
node[rt].r1 = node[rt << 1 | 1].r1 + node[rt << 1].r1;
else
node[rt].r1 = node[rt << 1 | 1].r1;
if (node[rt << 1].l0 == lenl)
node[rt].l0 = node[rt << 1].l0 + node[rt << 1 | 1].l0;
else
node[rt].l0 = node[rt << 1].l0;
if (node[rt << 1 | 1].r0 == lenr)
node[rt].r0 = node[rt << 1 | 1].r0 + node[rt << 1].r0;
else
node[rt].r0 = node[rt << 1 | 1].r0;
node[rt].m1 = max(node[rt << 1].r1 + node[rt << 1 | 1].l1,
max(node[rt << 1].m1, node[rt << 1 | 1].m1));
node[rt].m0 = max(node[rt << 1].r0 + node[rt << 1 | 1].l0,
max(node[rt << 1].m0, node[rt << 1 | 1].m0));
}
void pushdown(int rt, int l, int r) {
int m = (l + r) >> 1;
int lenl = m - l + 1;
int lenr = r - m;
if (cover[rt] != -1) {
if (cover[rt] == 1) {
node[rt << 1] = Node(lenl, lenl, lenl, lenl, 0, 0, 0);
node[rt << 1 | 1] = Node(lenr, lenr, lenr, lenr, 0, 0, 0);
}
else {
node[rt << 1] = Node(0, 0, 0, 0, lenl, lenl, lenl);
node[rt << 1 | 1] = Node(0, 0, 0, 0, lenr, lenr, lenr);
}
cover[rt << 1] = cover[rt << 1 | 1] = cover[rt];
XOR[rt << 1] = XOR[rt << 1 | 1] = 0;
cover[rt] = -1;
}
if (XOR[rt] != 0) {
node[rt << 1].reversal(lenl - node[rt << 1].c1);
node[rt << 1 | 1].reversal(lenr - node[rt << 1 | 1].c1);
if (cover[rt << 1] != -1)
cover[rt << 1] = 1 - cover[rt << 1];
else
XOR[rt << 1] = 1 - XOR[rt << 1];
if (cover[rt << 1 | 1] != -1)
cover[rt << 1 | 1] = 1 - cover[rt << 1 | 1];
else
XOR[rt << 1 | 1] = 1 - XOR[rt << 1 | 1];
XOR[rt] = 0;
}
}
void build(int l, int r, int rt) {
cover[rt] = -1;
XOR[rt] = 0;
if (l == r) {
int x;
scanf("%d", &x);
node[rt] = Node(x, x, x, x, 1 - x, 1 - x, 1 - x);
return ;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
pushup(rt, l, r);
}
void update(int op, int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) {
if (op == 2) {
node[rt].reversal(r - l + 1 - node[rt].c1);
if (cover[rt] != -1)
cover[rt] = 1 - cover[rt];
else
XOR[rt] = 1 - XOR[rt];
}
else {
node[rt] = (op == 0 ? Node(0, 0, 0, 0, r - l + 1, r - l + 1, r - l + 1) :
Node(r - l + 1, r - l + 1, r - l + 1, r - l + 1, 0, 0, 0));
cover[rt] = op;
XOR[rt] = 0;
}
return ;
}
pushdown(rt, l, r);
int m = (l + r) >> 1;
if (L <= m)
update(op, L, R, lson);
if (R > m)
update(op, L, R, rson);
pushup(rt, l, r);
}
Node query(int op, int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) {
return node[rt];
}
pushdown(rt, l, r);
int m = (l + r) >> 1;
Node ql = Node(0, 0, 0, 0, 0, 0, 0);
Node qr = Node(0, 0, 0, 0, 0, 0, 0);
if (L <= m)
ql = query(op, L, R, lson);
if (R > m)
qr = query(op, L, R, rson);
pushup(rt, l, r);
if (op == 3) {
return Node(ql.c1 + qr.c1, 0, 0, 0, 0, 0, 0);
}
else {
Node res = Node(0, 0, 0, 0, 0, 0, 0);
res.m1 = max(ql.r1 + qr.l1, max(ql.m1, qr.m1));
if (ql.l1 == m - l + 1)
res.l1 = ql.l1 + qr.l1;
else
res.l1 = ql.l1;
if (qr.r1 == r - m)
res.r1 = qr.r1 + ql.r1;
else
res.r1 = qr.r1;
return res;
}
}
int main() {
int t_case;
scanf("%d", &t_case);
for (int i_case = 1; i_case <= t_case; i_case++) {
int n, m;
scanf("%d%d", &n, &m);
build(1, n, 1);
for (int i = 0; i < m; i++) {
int op, a, b;
scanf("%d%d%d", &op, &a, &b);
a++;
b++;
if (op <= 2) {
update(op, a, b, 1, n, 1);
}
else {
Node res = query(op, a, b, 1, n, 1);
if (op == 3)
printf("%d\n", res.c1);
else
printf("%d\n", res.m1);
}
}
}
return 0;
}
HDU 3397 Sequence operation(区间合并 + 区间更新)的更多相关文章
- 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 3397 Sequence operation (线段树 区间合并 多重标记)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=3397 题意: 给你一串01串,有5种操作 0. 区间全部变为0 1.区间全部变为1 2.区间异或 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变 ...
- 【线段树】HDU 3397 Sequence operation 区间合并
操作 Change operations: 0 a b change all characters into '0's in [a , b] 1 a b change all characters i ...
- hdu 3397 Sequence operation(很有意思的线段树题)
Sequence operation Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- HDU 3397 Sequence operation
题目:下列操作 Change operations:0 a b change all characters into '0's in [a , b]1 a b change all character ...
- hdu 3397 Sequence operation(线段树:区间更新)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3397 题意:给你一个长度为n的0,1序列,支持下列五种操作, 操作0(0 a b):将a到b这个区间的 ...
- HDU 3397 Sequence operation (区间合并,操作比较多)
费了我一天半的时间,到处debug,后来才发现,主要是建树的时候只在叶子节点对lazy1和lazy2进行初始化了,父节点都没初始化...晕. 具体见代码吧. #include <iostream ...
- (简单) HDU 3397 Sequence operation,线段树+区间合并。
Problem Description lxhgww got a sequence contains n characters which are all '0's or '1's. We have ...
随机推荐
- Ubuntu 16.04下ssh启用root登录
debian里root账户默认没有密码,但账户锁定. 当需要root权限时, 直接执行 sudo su 即可切换为root用户. 重新开启root账号,在命令行下执行 sudo passwd root ...
- SQL的连接(外连接、内连接、交叉连接和自连接)
在查询多个表时,我们经常会用到连接查询,连接是关系型数据库的主要特点,也是它区别于其他类型的数据库管理系统的一个标志. 一.什么是连接查询 连接查询:根据两个表或者多个表的列之间的关系,来从这些表中查 ...
- IntelliJ IDEA 配合 Maven 的一些技巧:Profiles
环境 IntelliJ IDEA 2017.1 Maven 3.3.9 Nexus 3.2.1 学习前提 了解 Maven 配置的基本用法 了解私有仓库,比如 nexus 的一些概念 强烈建议把 Ma ...
- JComboBox添加item的赋值类型问题!不一致的话会导致不能更改jcombobox的选择值
在用swing做页面的时候,往往需要设置字体样式,那么,如何用一种方法设置字体之后,在后面的其他页面就不需要再次设置字体了呢? 下面这个方法就可以解决了: JComboBox在对它进行添加子项的时候, ...
- 文件流:"fopen","fclose",“ftell”"fseek","fgets","fprintf" ,“feof”,"fwrite","fread"
char const* filename="D:/hello.txt"; 路径名使用的是“/”或者使用 转义字符“\\”: "fopen", FILE *fp= ...
- JS方面重点摘要(一)
1.获取样式(1)style只能获取到行间样式的属性(2)火狐getComputedStyle(obj,null)[attr],IE:obj.currentStyle[attr] 2.ready.on ...
- CentOS 7.2安装lepus数据库监控系统
环境说明 系统版本 CentOS 7.2 x86_64 软件版本 lepus 3.7 Lepus是一套开源的数据库监控平台,目前已经支持MySQL.Oracle.SQLServer.MongoDB ...
- hibernate学习系列-----(5)hibernate基本查询下篇:hibernate聚合函数、分组查询及命名查询
在上一篇中,大致学习了hibernate的基本查询:HQL基本查询,今天,继续昨天的步伐,继续学习hibernate的基本查询..... 1.hql聚合函数,先大致列一下hql的聚合函数有哪些吧: 在 ...
- Oracle之索引(Index)实例解说 - 基础
Oracle之索引(Index)实例解说 - 基础 索引(Index)是关系数据库中用于存放表中每一条记录位置的一种对象.主要目的是加快数据的读取速度和数据的完整性检查.索引的建立是一项技术性要求很高 ...
- git merge 和 git rebase 小结(转)
git merge是用来合并两个分支的. git merge b # 将b分支合并到当前分支 同样 git rebase b,也是把 b分支合并到当前分支 ---------------------- ...