HDU 3397 Sequence operation 线段树综合题
2017-07-21 15:03
519 查看
题目地址
题意:给你个01串,有以下几种操作。
0.把[l.r]区间的所有数都置为0.
1.把[l.r]区间的所有数都置为1.
2.把[l,r]区间的所有数都置为其相反数.
3.求[l,r]区间内的1的个数.
4.求[l,r]区间内的最长的连续的’1’的个数.
思路:这题我写了一天多了,还是发现是因为急躁好多小细节没有考虑清楚。其实这题适合于刚刚把线段树学完的人来写,因为都是一些基础的操作拼接起来的。题目本身并不难。我来先简要说下我的想法吧。我有两个延时更新标记,一个是覆盖0或者1的标记flag,如果是0操作就把该标记置为0,如果是1操作就把该标记置为1,另一个是判断是否取反的标记x_or(wa一天的点就是2操作是在update的时候忘记把当前标记与1做异或操作,直接给改标记赋1了,导致如果对同一个区间做取反操作2次的结果还是取反)。
操作修改情况:
如果是覆盖操作的话,无论x_or为多少直接置为0,然后再把flag置为相应的值。
如果是取反操作的话,先把x_or标记取反,再看如果flag不为-1,并且该x_or标记为1,则flag与1做异或操作,x_or置为0。
输出情况:
输出1的个数就是最简单的线段树的输出
输出该区间最长的连续1的序列(这个就是线段树的区间合并的知识,就是更新时还要加上个中间合并的区间会不会造成更长的连续区间)
附线段树模板:戳这里
题意:给你个01串,有以下几种操作。
0.把[l.r]区间的所有数都置为0.
1.把[l.r]区间的所有数都置为1.
2.把[l,r]区间的所有数都置为其相反数.
3.求[l,r]区间内的1的个数.
4.求[l,r]区间内的最长的连续的’1’的个数.
思路:这题我写了一天多了,还是发现是因为急躁好多小细节没有考虑清楚。其实这题适合于刚刚把线段树学完的人来写,因为都是一些基础的操作拼接起来的。题目本身并不难。我来先简要说下我的想法吧。我有两个延时更新标记,一个是覆盖0或者1的标记flag,如果是0操作就把该标记置为0,如果是1操作就把该标记置为1,另一个是判断是否取反的标记x_or(wa一天的点就是2操作是在update的时候忘记把当前标记与1做异或操作,直接给改标记赋1了,导致如果对同一个区间做取反操作2次的结果还是取反)。
操作修改情况:
如果是覆盖操作的话,无论x_or为多少直接置为0,然后再把flag置为相应的值。
如果是取反操作的话,先把x_or标记取反,再看如果flag不为-1,并且该x_or标记为1,则flag与1做异或操作,x_or置为0。
输出情况:
输出1的个数就是最简单的线段树的输出
输出该区间最长的连续1的序列(这个就是线段树的区间合并的知识,就是更新时还要加上个中间合并的区间会不会造成更长的连续区间)
附线段树模板:戳这里
#include <iostream> #include <cstring> #include <string> #include <queue> #include <vector> #include <map> #include <set> #include <stack> #include <cmath> #include <cstdio> #include <algorithm> #define N 100010 #define LL long long #define inf 0x3f3f3f3f #define lson l,mid,ans<<1 #define rson mid+1,r,ans<<1|1 using namespace std; const LL mod = 1e9 + 7; const double eps = 1e-9; struct node { int l, r; int sum;//1的个数 int l0, r0, max0; int l1, r1, max1; int flag;//0,1覆盖标记 int x_or;//异或标记 }sum[N << 2];//线段树主体 struct Segment__Tree { int x, y; void pushUp(int ans) { sum[ans].sum = sum[ans << 1].sum + sum[ans << 1 | 1].sum; if (sum[ans << 1].l0 == (sum[ans << 1].r - sum[ans << 1].l + 1)) { sum[ans].l0 = sum[ans << 1].l0 + sum[ans << 1 | 1].l0; } else { sum[ans].l0 = sum[ans << 1].l0; } if (sum[ans << 1].l1 == (sum[ans << 1].r - sum[ans << 1].l + 1)) { sum[ans].l1 = sum[ans << 1].l1 + sum[ans << 1 | 1].l1; } else { sum[ans].l1 = sum[ans << 1].l1; } if (sum[ans << 1 | 1].r0 == (sum[ans << 1 | 1].r - sum[ans << 1 | 1].l + 1)) { sum[ans].r0 = sum[ans << 1].r0 + sum[ans << 1 | 1].r0; } else { sum[ans].r0 = sum[ans << 1 | 1].r0; } if (sum[ans << 1 | 1].r1 == (sum[ans << 1 | 1].r - sum[ans << 1 | 1].l + 1)) { sum[ans].r1 = sum[ans << 1].r1 + sum[ans << 1 | 1].r1; } else { sum[ans].r1 = sum[ans << 1 | 1].r1; } sum[ans].max0 = max(max(max(sum[ans << 1].max0, sum[ans << 1 | 1].max0), max(sum[ans].l0, sum[ans].r0)), sum[ans << 1].r0 + sum[ans << 1 | 1].l0); sum[ans].max1 = max(max(max(sum[ans << 1].max1, sum[ans << 1 | 1].max1), max(sum[ans].l1, sum[ans].r1)), sum[ans << 1].r1 + sum[ans << 1 | 1].l1); } void pushDown(int ans) { if (sum[ans].flag == 0) { int l = sum[ans << 1].l; int r = sum[ans << 1].r; sum[ans << 1].sum = 0; sum[ans << 1].l0 = r - l + 1; sum[ans << 1].r0 = r - l + 1; sum[ans << 1].max0 = r - l + 1; sum[ans << 1].l1 = 0; sum[ans << 1].r1 = 0; sum[ans << 1].max1 = 0; sum[ans << 1].flag = 0; l = sum[ans << 1 | 1].l; r = sum[ans << 1 | 1].r; sum[ans << 1 | 1].sum = 0; sum[ans << 1 | 1].l0 = r - l + 1; sum[ans << 1 | 1].r0 = r - l + 1; sum[ans << 1 | 1].max0 = r - l + 1; sum[ans << 1 | 1].l1 = 0; sum[ans << 1 | 1].r1 = 0; sum[ans << 1 | 1].max1 = 0; sum[ans << 1 | 1].flag = 0; sum[ans << 1].x_or = 0; sum[ans << 1 | 1].x_or = 0; } else if (sum[ans].flag == 1) { int l = sum[ans << 1].l; int r = sum[ans << 1].r; sum[ans << 1].l0 = 0; sum[ans << 1].r0 = 0; sum[ans << 1].max0 = 0; sum[ans << 1].sum = r - l + 1; sum[ans << 1].l1 = r - l + 1; sum[ans << 1].r1 = r - l + 1; sum[ans << 1].max1 = r - l + 1; sum[ans << 1].flag = 1; l = sum[ans << 1 | 1].l; r = sum[ans << 1 | 1].r; sum[ans << 1 | 1].l0 = 0; sum[ans << 1 | 1].r0 = 0; sum[ans << 1 | 1].max0 = 0; sum[ans << 1 | 1].sum = r - l + 1; sum[ans << 1 | 1].l1 = r - l + 1; sum[ans << 1 | 1].r1 = r - l + 1; sum[ans << 1 | 1].max1 = r - l + 1; sum[ans << 1 | 1].flag = 1; sum[ans << 1].x_or = 0; sum[ans << 1 | 1].x_or = 0; } if (sum[ans].x_or) { int l = sum[ans << 1].l; int r = sum[ans << 1].r; sum[ans << 1].sum = r - l + 1 - sum[ans << 1].sum; swap(sum[ans << 1].l0, sum[ans << 1].l1); swap(sum[ans << 1].r0, sum[ans << 1].r1); swap(sum[ans << 1].max0, sum[ans << 1].max1); l = sum[ans << 1 | 1].l; r = sum[ans << 1 | 1].r; sum[ans << 1 | 1].sum = r - l + 1 - sum[ans << 1 | 1].sum; swap(sum[ans << 1 | 1].l0, sum[ans << 1 | 1].l1); swap(sum[ans << 1 | 1].r0, sum[ans << 1 | 1].r1); swap(sum[ans << 1 | 1].max0, sum[ans << 1 | 1].max1); sum[ans << 1].x_or ^= 1; sum[ans << 1 | 1].x_or ^= 1; } sum[ans].flag = -1; sum[ans].x_or = 0; } void build(int l, int r, int ans) { sum[ans].l = l; sum[ans].r = r; sum[ans].flag = -1; sum[ans].x_or = 0; if (l == r) { cin >> sum[ans].sum; if (sum[ans].sum == 0) { sum[ans].l0 = 1; sum[ans].r0 = 1; sum[ans].max0 = 1; sum[ans].l1 = 0; sum[ans].r1 = 0; sum[ans].max1 = 0; } else { sum[ans].l0 = 0; sum[ans].r0 = 0; sum[ans].max0 = 0; sum[ans].l1 = 1; sum[ans].r1 = 1; sum[ans].max1 = 1; } return; } int mid = (l + r) >> 1; build(lson); build(rson); pushUp(ans); } int solve(int l, int r, int ans, int nums) { if (l >= x&&r <= y) { if (nums) { return sum[ans].max1; } return sum[ans].sum; } int mid = (l + r) >> 1; pushDown(ans); if (mid<x) { return solve(rson, nums); } else if (mid >= y) { return solve(lson, nums); } else { if (nums) { return max(max(solve(lson, nums), solve(rson, nums)), min(sum[ans << 1].r - x + 1, sum[ans << 1].r1) + min(y - sum[ans << 1 | 1].l + 1, sum[ans << 1 | 1].l1)); } return solve(lson, nums) + solve(rson, nums); } } void updata(int l, int r, int ans, int num) { if (l >= x&&r <= y) { if (num == 0) { sum[ans].sum = 0; sum[ans].l0 = r - l + 1; sum[ans].r0 = r - l + 1; sum[ans].max0 = r - l + 1; sum[ans].l1 = 0; sum[ans].r1 = 0; sum[ans].max1 = 0; sum[ans].flag = 0; sum[ans].x_or = 0; } else if(num == 1){ sum[ans].sum = r - l + 1; sum[ans].l0 = 0; sum[ans].r0 = 0; sum[ans].max0 = 0; sum[ans].l1 = r - l + 1; sum[ans].r1 = r - l + 1; sum[ans].max1 = r - l + 1; sum[ans].flag = 1; sum[ans].x_or = 0; } else if (num == 2) { sum[ans].sum = r - l + 1 - sum[ans].sum; swap(sum[ans].l0, sum[ans].l1); swap(sum[ans].r0, sum[ans].r1); swap(sum[ans].max0, sum[ans].max1); sum[ans].x_or ^= 1; if (sum[ans].flag != -1 && sum[ans].x_or == 1) { sum[ans].flag ^= 1; sum[ans].x_or = 0; } } return; } int mid = (l + r) >> 1; pushDown(ans); if (mid<x) { updata(rson, num); } else if (mid >= y) { updata(lson, num); } else { updata(lson, num); updata(rson, num); } pushUp(ans); } }; int main() { cin.sync_with_stdio(false); int c; int s; int n, q; Segment__Tree tree; int T; cin >> T; while (T--) { cin >> n >> q; tree.build(1, n, 1); while (q--) { cin >> s >> tree.x >> tree.y; tree.x++; tree.y++; if (s == 0) { tree.updata(1, n, 1, 0); } else if (s == 1) { tree.updata(1, n, 1, 1); } else if (s == 2) { tree.updata(1, n, 1, 2); } else if (s == 3) { cout << tree.solve(1, n, 1, 0) << endl; } else { cout << tree.solve(1, n, 1, 1) << endl; } } } return 0; }
相关文章推荐
- hdu 3397(线段树综合题)
- HDU 3397 Sequence operation (线段树)
- 【线段树】HDU 3397 Sequence operation 区间合并
- HDU 3397(线段树,较难~)
- HDU 3397 Sequence opera 4000 tion(线段树综合操作)
- hdu 3397 Sequence operation 线段树
- hdu 3911, 3397 线段树 lazy tag
- HDU 3397 Sequence operation(线段树好题)
- HDU 3397 Sequence operation (线段树)
- HDU 3397 Sequence operation(线段树:成段更新,查询连续目标子串长度)
- hdu 3397 Sequence operation 线段树
- M - Sequence operation HDU - 3397 线段树,成段更新,区间合并)
- hdu 3397 Sequence operation(线段树的延迟标记)
- HDU 3397 Sequence operation(线段树的区间合并)
- hdu 3397 Sequence Operation 线段树维护区间前后缀和,求子区间连续最值
- HDU 3397 Sequence operation(线段树区间合并+区间修改)
- HDU 3397 线段树 双懒惰标记
- POJ 3667 & HDU 3308 & HDU 3397 线段树的区间合并
- HDU-3397 线段树+区间合并
- Hdu 3397 Sequence operation(线段树多操作,Lazy思想,成段更新)