线段树 HDU 3397 Sequence operation
2012-08-30 21:43
363 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3397
代码风格:http://www.notonlysuccess.com/index.php/segment-tree-complete/
题目大意:操作说明:0——把[a,b]区间全部变成0;1——把[a, b]区间全部变成1;2——把[a,b]区间0,1取反;3——输出[a,b]区间1的个数;4——输出[a, b]区间最长连续1的长度
算法:线段树 区间合并
思路:0,1 操作如果不会可以去做一下POJ3367,代码见http://www.notonlysuccess.com/index.php/segment-tree-complete/
同时统计0和1的左边连续个数lsun,lsum,右边连续个数rsun,rsum,区间最长连续个数msun,msum以及区间内1的个数p
0,1操作时,把取反标记清零
2操作:建立数组x[]作为取反标记,并且lsum,rsun互换,rsum,rsun互换,msum, msun互换,p改变
代码风格:http://www.notonlysuccess.com/index.php/segment-tree-complete/
题目大意:操作说明:0——把[a,b]区间全部变成0;1——把[a, b]区间全部变成1;2——把[a,b]区间0,1取反;3——输出[a,b]区间1的个数;4——输出[a, b]区间最长连续1的长度
算法:线段树 区间合并
思路:0,1 操作如果不会可以去做一下POJ3367,代码见http://www.notonlysuccess.com/index.php/segment-tree-complete/
同时统计0和1的左边连续个数lsun,lsum,右边连续个数rsun,rsum,区间最长连续个数msun,msum以及区间内1的个数p
0,1操作时,把取反标记清零
2操作:建立数组x[]作为取反标记,并且lsum,rsun互换,rsum,rsun互换,msum, msun互换,p改变
#include"cstdio" #include"cstring" #include"cmath" #include"algorithm" using namespace std; const int Max = 444444; #define lson l, m, rt << 1 #define rson m+1, r, rt << 1 | 1 #define mid int m = (l+r) >> 1 int lsun[Max], rsun[Max], msun[Max]; int rsum[Max], lsum[Max], msum[Max]; int cover[Max], p[Max], x[Max]; void fxor(int rt) { if(cover[rt] != -1) cover[rt] ^= 1; else x[rt] ^= 1; } int max(int a, int b) { return a > b ? a : b; } int min(int a, int b) { return a < b ? a : b; } void PushUp(int l, int r, int rt, int m) { //printf("%d -- %d, rt == %d\n", p[rt << 1 ], p[rt << 1 | 1], rt); p[rt] = p[rt << 1 ] + p[rt << 1 | 1]; rsum[rt] = rsum[rt << 1 | 1]; rsun[rt] = rsun[rt << 1 | 1]; lsum[rt] = lsum[rt << 1]; lsun[rt] = lsun[rt << 1]; if(lsun[rt] == m - (m >> 1)) lsun[rt] += lsun[rt << 1 | 1]; if(lsum[rt] == m - (m >> 1)) lsum[rt] += lsum[rt << 1 | 1]; if(rsun[rt] == m >> 1) rsun[rt] += rsun[rt << 1]; if(rsum[rt] == m >> 1) rsum[rt] += rsum[rt << 1]; msum[rt] = max(max(msum[rt << 1], msum[rt << 1 | 1]), lsum[rt << 1 | 1] + rsum[rt << 1]); msun[rt] = max(max(msun[rt << 1], msun[rt << 1 | 1]), lsun[rt << 1 | 1] + rsun[rt << 1 ]); } void PushDown(int rt, int m) { if(cover[rt] != -1) { cover[rt << 1] = cover[rt << 1 | 1] = cover[rt]; msum[rt << 1] = rsum[rt << 1] = lsum[rt << 1] = p[rt << 1] = cover[rt] * (m - (m >> 1)); msum[rt << 1 | 1] = rsum[rt << 1 | 1] = lsum[rt << 1 | 1] = p[rt << 1 | 1] = cover[rt] * (m >> 1); msun[rt << 1] = rsun[rt << 1] = lsun[rt << 1] = cover[rt] ? 0 : m - (m >> 1); msun[rt << 1 | 1] = rsun[rt << 1 | 1] = lsun[rt << 1 | 1] = cover[rt] ?0 : m >> 1; x[rt << 1] = x[rt << 1 | 1] = 0; cover[rt] = -1; } if(x[rt] != 0) { fxor(rt << 1); fxor(rt << 1 | 1); p[rt << 1] = (m - (m >> 1)) - p[rt << 1]; p[rt << 1 | 1] = (m >> 1) - p[rt << 1 | 1]; int k = lsum[rt << 1]; lsum[rt << 1] = lsun[rt << 1]; lsun[rt << 1] = k; k = rsum[rt << 1]; rsum[rt << 1] = rsun[rt << 1]; rsun[rt << 1] = k; k = msum[rt << 1]; msum[rt << 1] = msun[rt << 1]; msun[rt << 1] = k; k = lsum[rt << 1 | 1]; lsum[rt << 1 | 1] = lsun[rt << 1 | 1]; lsun[rt << 1 | 1] = k; k = rsum[rt << 1 | 1]; rsum[rt << 1 | 1] = rsun[rt << 1 | 1]; rsun[rt << 1 | 1] = k; k = msum[rt << 1 | 1]; msum[rt << 1 | 1] = msun[rt << 1 | 1]; msun[rt << 1 | 1] = k; x[rt] = 0; } } void build(int l, int r, int rt) { if(l == r) { scanf("%d", &p[rt]); rsum[rt] = msum[rt] = lsum[rt] = p[rt] ? 1 : 0; rsun[rt] = msun[rt] = lsun[rt] = p[rt] ? 0 : 1; //printf("msum[rt] = %d\n", msum[rt]); return ; } mid ; build(lson); build(rson); PushUp(m, m+1, rt, r-l+1); } void update(int op, int L, int R, int l, int r, int rt) { if(L <= l && r <= R) { if(op == 2) { p[rt] = r-l+1-p[rt]; int k = lsum[rt]; lsum[rt] = lsun[rt]; lsun[rt] = k; k = rsum[rt]; rsum[rt] = rsun[rt]; rsun[rt] = k; k = msum[rt]; msum[rt] = msun[rt]; msun[rt] = k; fxor(rt); } else { cover[rt] = op; lsum[rt] = msum[rt] = rsum[rt] = p[rt] = op ? r-l+1 : 0; lsun[rt] = msun[rt] = rsun[rt] = op ? 0 : r-l+1; x[rt] = 0; } return ; } mid ; PushDown(rt, r-l+1); if(L <= m) update(op, L, R, lson); if(m < R) update(op, L, R, rson); PushUp(m, m+1, rt, r-l+1); } int query(int L, int R, int l, int r, int rt) { if(L <= l && r <= R) { return p[rt]; } int ret = 0; PushDown(rt, r-l+1); mid; if(L <= m) ret += query(L, R, lson); if(m < R) ret += query(L, R, rson); return ret ; } int Query(int L, int R, int l, int r, int rt) { if(L <= l && r <= R) { return msum[rt]; } mid; PushDown(rt, r-l+1); if(m < L) return Query(L, R, rson); else if(R <= m) return Query(L, R, lson); return max(max(min(rsum[rt << 1], m+1-L) + min(lsum[rt << 1 | 1], R-m), Query(L, R, lson)), Query(L, R, rson) ); } int main() { int T, n, m; scanf("%d", &T); while( T --) { memset(x, 0, sizeof(x)); memset(cover, -1, sizeof(cover)); scanf("%d%d", &n, &m); build(0, n-1, 1); while(m --) { int a, b, c; scanf("%d%d%d", &a, &b, &c); if(a < 3) update(a, b, c, 0, n-1, 1); else if(a == 3) printf("%d\n", query(b, c, 0, n-1, 1)); else printf("%d\n", Query(b, c, 0, n-1, 1)); } } return 0; }
相关文章推荐
- HDU 3397 Sequence operation 线段树
- Hdu 3397 Sequence operation(线段树多操作,Lazy思想,成段更新)
- HDU 3397 Sequence operation(线段树)
- M - Sequence operation HDU - 3397 线段树,成段更新,区间合并)
- hdu 3397 Sequence operation(线段树的各种操作)
- HDU 3397 线段树区间合并
- hdu 3911, 3397 线段树 lazy tag
- HDU 3397 Sequence operation (线段树区间合并入门)
- hdu 3397 Sequence operation(线段树区间覆盖,区间合并)
- HDU 3397 Sequence operation 线段树
- HDU 3397 线段树 双懒惰标记
- HDU 3397 Sequence operation (线段树)
- HDU 3397 Sequence operation(线段树的区间合并)
- HDU 3397 Sequence operation(线段树区间合并)
- HDU - 3397 Sequence operation(线段树)
- hdu 3397 Sequence operation 线段树
- hdu 3397 Sequence operation 线段树 区间更新 区间合并
- hdu 3397 Sequence operation(线段树,lazy,区间合并)
- HDU 3397 Sequence operation(线段树)
- HDU 3397 Sequence operation(线段树好题)