hdu 3911, 3397 线段树 lazy tag
来源:互联网 发布:表白楼宇生成器软件 编辑:程序博客网 时间:2024/06/09 19:22
hdu 3911
题意:
0, 1序列
两种操作:
1. 将一段区间内的 0 与 1 翻转
2. 询问一段区间内最长的连续的 1 的个数
对于每个区间而言记录如下信息:
左起连续的 1 的个数,右起连续的 1 的个数,整段区间最长的连续的 1 的个数
左起连续的 0 的个数,右起连续的 0 的个数,整段区间最长的连续的 0 的个数
之所以要记录 0 是为了方便翻转后信息的修改
显见,这些信息记录下来后,就不需要具体地知道每个位置究竟是 0 还是 1 了
然后再注意一下合并的细节之类的就行了
但是这道题有个很 tricky 的地方(也许只是我个人这么觉得…)
对于 tag 的修改(在 modify 时以及 push_down 时)并不能直接置 1,要注意到 tag 的叠加性,也许这次的修改是恰好抵消了前一次的修改呢
(致谢点击打开链接,还是在看了原PO写的之后才意识到原来WA在了这里...)
AC代码如下:
#include <cstdio>#define lson ((rt) << 1)#define rson ((rt) << 1 | 1)#define maxn 100010inline max(int a, int b) { return a > b ? a : b; }inline min(int a, int b) { return a < b ? a : b; }inline midi(int a, int b) { return (a + b) >> 1; }inline swap(int& a, int& b) { int temp = a; a = b; b = temp; }struct node { int l1, l0, r1, r0, t1, t0, len, l, r; bool flag;}tree[maxn * 4];int n, m;void lift_up(int rt) { tree[rt].l1 = tree[lson].l1; tree[rt].l0 = tree[lson].l0; if (tree[rt].l1 == tree[lson].len) tree[rt].l1 += tree[rson].l1; if (tree[rt].l0 == tree[lson].len) tree[rt].l0 += tree[rson].l0; tree[rt].r1 = tree[rson].r1; tree[rt].r0 = tree[rson].r0; if (tree[rt].r1 == tree[rson].len) tree[rt].r1 += tree[lson].r1; if (tree[rt].r0 == tree[rson].len) tree[rt].r0 += tree[lson].r0; tree[rt].t1 = max(max(tree[lson].t1, tree[rson].t1), tree[lson].r1 + tree[rson].l1); tree[rt].t0 = max(max(tree[lson].t0, tree[rson].t0), tree[lson].r0 + tree[rson].l0);}void build(int rt, int l, int r) { tree[rt].l = l; tree[rt].r = r; tree[rt].len = r - l + 1; tree[rt].flag = 0; if (l == r) { int x; scanf("%d", &x); tree[rt].l1 = tree[rt].r1 = tree[rt].t1 = x; tree[rt].l0 = tree[rt].r0 = tree[rt].t0 = 1 - x; return; } int mid = midi(l, r); build(lson, l, mid); build(rson, mid + 1, r); lift_up(rt);}void push_down(int rt) { if (tree[rt].flag) { swap(tree[lson].l1, tree[lson].l0); swap(tree[lson].r1, tree[lson].r0); swap(tree[lson].t1, tree[lson].t0); swap(tree[rson].l1, tree[rson].l0); swap(tree[rson].r1, tree[rson].r0); swap(tree[rson].t1, tree[rson].t0); tree[lson].flag ^= 1; tree[rson].flag ^= 1; tree[rt].flag = 0; }}int query(int rt, int l, int r) { if (tree[rt].l == l && tree[rt].r == r) return tree[rt].t1; push_down(rt); int mid = midi(tree[rt].l, tree[rt].r); if (r <= mid) return query(lson, l, r); else if (l > mid) return query(rson, l, r); else { int ans1 = query(lson, l, mid), ans2 = query(rson, mid + 1, r), ans3 = min(mid - l + 1, tree[lson].r1) + min(r - mid, tree[rson].l1); return max(max(ans1, ans2), ans3); }}void modify(int rt, int l, int r) { if (tree[rt].l == l && tree[rt].r == r) { swap(tree[rt].l1, tree[rt].l0); swap(tree[rt].r1, tree[rt].r0); swap(tree[rt].t1, tree[rt].t0); tree[rt].flag ^= 1; return; } push_down(rt); int mid = midi(tree[rt].l, tree[rt].r); if (r <= mid) modify(lson, l, r); else if (l > mid) modify(rson, l, r); else { modify(lson, l, mid); modify(rson, mid + 1, r); } lift_up(rt);}void work() { build(1, 1, n); scanf("%d", &m); for (int i = 0; i < m; ++i) { int x, l, r; scanf("%d%d%d", &x, &l, &r); if (x == 0) printf("%d\n", query(1, l, r)); else modify(1, l, r); }}int main() { while (scanf("%d", &n) != EOF) work(); return 0;}
hdu 3397
题意:
0, 1序列
五种操作:
1. 将一段区间全置 0
2. 将一段区间全置 1
3. 将一段区间 0, 1 翻转
4. 询问一段区间内 1 的总数
5. 询问一段区间内最长的连续的 1 的个数
显见对于连续的 1 的个数的处理和上一题(hdu 3911)一模一样
而 1 的总数的记录就是最简单的那样
所以这道题关键的地方就在于 tag 怎么处理
用了两个 tag,来分别表示 第三种操作(flag1) 和 前两种操作(flag2),
在,分别初始化为 flag1 = 0, flag2 = -1
(事实上,对于 flag1 的处理和上一题中一模一样)
显见,前两种操作的优先级是比第三种操作要高的,所以
在 push_down 时,首先根据 flag2 来 push,如果 flag2 == -1,再去根据 flag1 来 push;
在 modify 时,
如果当前操作是前两种操作,那么直接修改flag2;
如果当前操作是第三种操作,如果 flag2 != -1(这意味着记录下的当前段的状态是全 0 或 全 1,第三种操作进行后也是变为 全 1 或 全 0), 那么 flag2 取反;否则修改 flag1
(顺便说一句,这道题写完后根本不想检查
然后
一遍A的感觉真是太爽了库库库)
AC代码如下:
#include <cstdio>#define lson ((rt) << 1)#define rson ((rt) << 1 | 1)#define maxn 100010inline max(int a, int b) { return a > b ? a : b; }inline min(int a, int b) { return a < b ? a : b; }inline midi(int a, int b) { return (a + b) >> 1; }inline swap(int& a, int& b) { int temp = a; a = b; b = temp; }int n, m;struct node { int l, r, num, l1, l0, r1, r0, t1, t0, len, flag1, flag2;}tree[maxn * 4];void lift_up(int rt) { tree[rt].num = tree[lson].num + tree[rson].num; tree[rt].l1 = tree[lson].l1; tree[rt].r1 = tree[rson].r1; if (tree[rt].l1 == tree[lson].len) tree[rt].l1 += tree[rson].l1; if (tree[rt].r1 == tree[rson].len) tree[rt].r1 += tree[lson].r1; tree[rt].l0 = tree[lson].l0; tree[rt].r0 = tree[rson].r0; if (tree[rt].l0 == tree[lson].len) tree[rt].l0 += tree[rson].l0; if (tree[rt].r0 == tree[rson].len) tree[rt].r0 += tree[lson].r0; tree[rt].t1 = max(max(tree[lson].t1, tree[rson].t1), tree[lson].r1 + tree[rson].l1); tree[rt].t0 = max(max(tree[lson].t0, tree[rson].t0), tree[lson].r0 + tree[rson].l0);}void push_down(int rt) { if (tree[rt].flag2 != -1) { tree[lson].l1 = tree[lson].r1 = tree[lson].t1 = tree[lson].num = tree[rt].flag2 * tree[lson].len; tree[lson].l0 = tree[lson].r0 = tree[lson].t0 = (1 - tree[rt].flag2) * tree[lson].len; tree[rson].l1 = tree[rson].r1 = tree[rson].t1 = tree[rson].num = tree[rt].flag2 * tree[rson].len; tree[rson].l0 = tree[rson].r0 = tree[rson].t0 = (1 - tree[rt].flag2) * tree[rson].len; tree[lson].flag2 = tree[rson].flag2 = tree[rt].flag2; tree[rt].flag2 = -1; tree[rt].flag1 = 0; return; } if (tree[rt].flag1) { swap(tree[lson].l1, tree[lson].l0); swap(tree[lson].r1, tree[lson].r0); swap(tree[lson].t1, tree[lson].t0); tree[lson].num = tree[lson].len - tree[lson].num; swap(tree[rson].l1, tree[rson].l0); swap(tree[rson].r1, tree[rson].r0); swap(tree[rson].t1, tree[rson].t0); tree[rson].num = tree[rson].len - tree[rson].num; if (tree[lson].flag2 != -1) tree[lson].flag2 = 1 - tree[lson].flag2; else tree[lson].flag1 ^= 1; if (tree[rson].flag2 != -1) tree[rson].flag2 = 1 - tree[rson].flag2; else tree[rson].flag1 ^= 1; tree[rt].flag2 = -1; tree[rt].flag1 = 0; }}void build(int rt, int l, int r) { tree[rt].l = l; tree[rt].r = r; tree[rt].len = r - l + 1; tree[rt].flag1 = 0; tree[rt].flag2 = -1; if (l == r) { int x; scanf("%d", &x); tree[rt].num = tree[rt].l1 = tree[rt].r1 = tree[rt].t1 = x; tree[rt].l0 = tree[rt].r0 = tree[rt].t0 = 1 - x; return; } int mid = midi(l, r); build(lson, l, mid); build(rson, mid + 1, r); lift_up(rt);}void modify(int rt, int l, int r, int x) {// printf("%d\n", rt); if (tree[rt].l == l && tree[rt].r == r) { if (x == 0 || x == 1) { tree[rt].num = tree[rt].l1 = tree[rt].r1 = tree[rt].t1 = x * tree[rt].len; tree[rt].l0 = tree[rt].r0 = tree[rt].t0 = (1 - x) * tree[rt].len; tree[rt].flag2 = x; tree[rt].flag1 = 0; } else { tree[rt].num = tree[rt].len - tree[rt].num; swap(tree[rt].l1, tree[rt].l0); swap(tree[rt].r1, tree[rt].r0); swap(tree[rt].t1, tree[rt].t0); if (tree[rt].flag2 != -1) tree[rt].flag2 = 1 - tree[rt].flag2; else tree[rt].flag1 ^= 1; } return; } push_down(rt); int mid = midi(tree[rt].l, tree[rt].r); if (r <= mid) modify(lson, l, r, x); else if (l > mid) modify(rson, l, r, x); else { modify(lson, l, mid, x); modify(rson, mid + 1, r, x); } lift_up(rt);}int query(int rt, int l, int r, int x) {// printf("%d\n", rt); if (tree[rt].l == l && tree[rt].r == r) { if (x == 0) return tree[rt].num; return tree[rt].t1; } push_down(rt); int mid = midi(tree[rt].l, tree[rt].r); if (r <= mid) return query(lson, l, r, x); else if (l > mid) return query(rson, l, r, x); else { if (x == 0) return query(lson, l, mid, x) + query(rson, mid + 1, r, x); else { int ans1 = query(lson, l, mid, x), ans2 = query(rson, mid + 1, r, x), ans3 = min(mid - l + 1, tree[lson].r1) + min(r - mid, tree[rson].l1); return max(max(ans1, ans2), ans3); } }}void work() { build(1, 1, n); for (int i = 0; i < m; ++i) { int op, l, r; scanf("%d%d%d", &op, &l, &r); ++l; ++r; switch (op) { case 0: case 1: case 2: modify(1, l, r, op); break; case 3: case 4: printf("%d\n", query(1, l, r, op - 3)); break; } }}int main() {// freopen("3397.in", "r", stdin); int T; scanf("%d", &T); while (scanf("%d%d", &n, &m) != EOF) work(); return 0;}
- hdu 3911, 3397 线段树 lazy tag
- 线段树Lazy-tag
- 线段树及Lazy-Tag
- 线段树 lazy tag 小合集
- 线段树多lazy-tag(两个)
- POJ3468 线段树 + Lazy Tag (延迟标记)
- HDU 1698Just a Hook(线段树 + Lazy Tag(延迟更新))
- hdu 3954 Level up 线段树 升级版Lazy tag 区间整体的性质
- hdu 1556 lazy线段树
- POJ 3667 Hotel 【线段树 区间合并 + Lazy-tag】
- AHOI2009维护序列--线段树lazy tag模板
- 线段树——区间修改(Lazy-Tag)
- HDU 3911 线段树 LAZY操作+成段更新
- hdu 3397 Sequence operation(线段树,lazy,区间合并)
- hdu(4325)线段树+离散化+lazy
- HDU 3954 线段树 特殊LAZY操作
- HDU 4578 线段树 多lazy操作
- hdu 4578 线段树lazy标记
- 从今天开始学习设计模式
- poj 2528Mayor's posters(线段树)(第二部分成段更新 离散化)
- NYOJ 873 环之最大和
- 【C语言】实现彩色的进度条
- 深度优先搜索的基础
- hdu 3911, 3397 线段树 lazy tag
- Windows Internals – 0 开篇
- FPGA学习笔记:面向验证和仿真的行为描述语句(3)
- Java注解(Annotation)详解(三)——解析注解
- 批量微信筛选开通助手
- 【python】升级python后yum不能使用解决方法
- 并发(1)基本的线程机制
- 2. Add Two Numbers
- 百度地图与谷歌地球的偏差调整