hdu 3911 Black And White(线段树)
2014-10-29 15:50
387 查看
题目连接:hdu 3911 Black And White
题目大意:给定一个序列,然后有M次操作;
0 l r:表示询问l,r中最大连续1的个数
1 l r:表示将l,r区间上的数取反
解题思路:线段树的一种题型,区间合并,由于有一个取反的操作,所以对于每一个节点要维护6个值,包含连续0,1最长序列的长度,左边和右边的最长连续长度。须要注意的是,假设询问的区间最大值是从R[lson] + L[rson]来到,要推断是否比长度大于r - l + 1。一開始没注意,所以WA了,上网搜了下别人的题解,发现非常多人在query里面没有pushup更新当前节点信息,这样肯定是不行的,有pushdown,肯定要在更新当前节点信息的。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 1e5 + 5; int N, M, a[maxn]; #define lson(x) ((x)<<1) #define rson(x) (((x)<<1)|1) int lc[maxn << 2], rc[maxn << 2], filp[maxn << 2]; int L[maxn << 2][2], R[maxn << 2][2], S[maxn << 2][2]; void maintain (int u) { filp[u] ^= 1; swap(L[u][0], L[u][1]); swap(R[u][0], R[u][1]); swap(S[u][0], S[u][1]); } void pushup(int u) { for (int i = 0; i < 2; i++) { S[u][i] = max(max(S[lson(u)][i], S[rson(u)][i]), R[lson(u)][i] + L[rson(u)][i]); L[u][i] = L[lson(u)][i] + (L[lson(u)][i] == rc[lson(u)] - lc[lson(u)] + 1 ? L[rson(u)][i] : 0); R[u][i] = R[rson(u)][i] + (R[rson(u)][i] == rc[rson(u)] - lc[rson(u)] + 1 ? R[lson(u)][i] : 0); } } void pushdown (int u) { if (filp[u]) { maintain(lson(u)); maintain(rson(u)); filp[u] = 0; } } void build (int u, int l, int r) { lc[u] = l; rc[u] = r; filp[u] = 0; if (l == r) { int d = a[l]; L[u][d] = R[u][d] = S[u][d] = 1; L[u][d^1] = R[u][d^1] = S[u][d^1] = 0; return ; } int mid = (l + r) / 2; build(lson(u), l, mid); build(rson(u), mid+1, r); pushup(u); } void modify (int u, int l, int r) { if (l <= lc[u] && rc[u] <= r) { maintain(u); return; } pushdown(u); int mid = (lc[u] + rc[u]) / 2; if (l <= mid) modify(lson(u), l, r); if (r > mid) modify(rson(u), l, r); pushup(u); } int query (int u, int l, int r) { if (l <= lc[u] && rc[u] <= r) return S[u][1]; pushdown(u); int mid = (lc[u] + rc[u]) / 2, ret; if (r <= mid) ret = query(lson(u), l, r); else if (l > mid) ret = query(rson(u), l, r); else { int ll = query(lson(u), l, r); int rr = query(rson(u), l, r); int a = min(L[rson(u)][1], r - mid); int b = min(R[lson(u)][1], mid - l + 1); ret = max( max(ll, rr), a + b); } pushup(u); return ret; } int main () { int x, l, r; while (scanf("%d", &N) == 1) { for (int i = 1; i <= N; i++) scanf("%d", &a[i]); build (1, 1, N); scanf("%d", &M); while (M--) { scanf("%d%d%d", &x, &l, &r); if (x) modify(1, l, r); else printf("%d\n", query(1, l, r)); } } return 0; }
相关文章推荐
- hdu 3911 Black And White (线段树)
- hdu 3911 Black And White(线段树的延迟标记法)
- HDU 3911 Black And White 线段树
- HDU 3911 Black And White (线段树区间更新)
- HDU 3911 Black And White(线段树区间合并)
- hdu 3911 Black And White 线段树区间合并
- hdu 3911 Black And White(线段树)
- hdu 3911 Black and White 线段树维护01序列
- HDU 3911 Black And White (线段树区间合并 + lazy标记)
- HDU 3911 Black And White 线段树
- HDU 3911 Black And White 2011 Multi-University Training Contest 8 - Host by HUST 线段树应用
- hdu 3911 Black And White(线段树)
- 【HDU - 3911】Black And White 【线段树+区间操作+区间合并】
- hdu 3911 Black And White 区间合并 线段树
- HDU 3911 Black And White(线段树区间合并+lazy操作)
- HDU 3911 Black And White(线段树区间合并+lazy操作)
- hdu 3911 black and white 线段树区间合并
- HDU-3911Black and White
- HDU 3911 Black And White
- hust 1546 && hdu 3911 Black And White