hdu 3911 Black And White (线段树 区间合并)
Posted kls123
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 3911 Black And White (线段树 区间合并)相关的知识,希望对你有一定的参考价值。
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3911
题意:
给你一段01序列,有两个操作:
1.区间异或,2.询问区间最长的连续的1得长度
思路:
线段树区间合并,开六个数组分别表示:
lsum0 区间左边界开始从左到右连续0的个数
rsum0 区间右边界开始从右到左连续0的个数
lsum1 rsum1 根据上面的可以看出
sum0 区间最长的连续0的个数
sum1 区间最长的连续1的个数
碰到i区间异或操作,我们直接奖这几个数组换下就好了
实现代码:
#include<bits/stdc++.h> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define mid int m = (l + r) >> 1 #define ll long long #define ull unsigned long long const int M = 1e5 + 10; int lsum1[M<<2],rsum1[M<<2],sum1[M<<2],lsum0[M<<2],rsum0[M<<2],sum0[M<<2],lazy[M<<2]; int a[M]; void pushup(int l,int r,int rt){ mid; lsum1[rt] = lsum1[rt<<1]; lsum0[rt] = lsum0[rt<<1]; rsum1[rt] = rsum1[rt<<1|1]; rsum0[rt] = rsum0[rt<<1|1]; if(lsum1[rt] == m-l+1) lsum1[rt] += lsum1[rt<<1|1]; if(rsum1[rt] == r-m) rsum1[rt] += rsum1[rt<<1]; if(lsum0[rt] == m-l+1) lsum0[rt] += lsum0[rt<<1|1]; if(rsum0[rt] == r-m) rsum0[rt] += rsum0[rt<<1]; sum0[rt] = max(max(sum0[rt<<1],sum0[rt<<1|1]),rsum0[rt<<1]+lsum0[rt<<1|1]); sum1[rt] = max(max(sum1[rt<<1],sum1[rt<<1|1]),rsum1[rt<<1]+lsum1[rt<<1|1]); } void swa(int rt){ swap(lsum0[rt],lsum1[rt]); swap(rsum0[rt],rsum1[rt]); swap(sum0[rt],sum1[rt]); } void pushdown(int l,int r,int rt){ if(lazy[rt]){ lazy[rt<<1] ^= lazy[rt]; lazy[rt<<1|1] ^= lazy[rt]; swa(rt<<1); swa(rt<<1|1); lazy[rt] = 0; } } void build(int l,int r,int rt){ lazy[rt] = 0; lsum1[rt] = rsum1[rt] = sum1[rt] = 0; lsum0[rt] = rsum0[rt] = sum0[rt] = 0; if(l == r){ if(a[l]){ lsum1[rt] = rsum1[rt] = sum1[rt] = 1; lsum0[rt] = rsum0[rt] = sum0[rt] = 0; } else{ lsum1[rt] = rsum1[rt] = sum1[rt] = 0; lsum0[rt] = rsum0[rt] = sum0[rt] = 1; } return ; } mid; build(lson); build(rson); pushup(l,r,rt); } void update(int L,int R,int l,int r,int rt){ if(L <= l&&R >= r){ lazy[rt] ^= 1; swa(rt); return ; } pushdown(l,r,rt); mid; if(L <= m) update(L,R,lson); if(R > m) update(L,R,rson); pushup(l,r,rt); } int query(int L,int R,int l,int r,int rt){ if(L <= l&&R >= r){ return sum1[rt]; } pushdown(l,r,rt); mid; if(L > m) return query(L,R,rson); if(R <= m) return query(L,R,lson); int t1 = query(L,R,lson); int t2 = query(L,R,rson); int rs = min(lsum1[rt<<1|1],R-m); int ls = min(m-L+1,rsum1[rt<<1]); return max(max(t1,t2),ls+rs); } int main() { int n,op,x,y,q; while(scanf("%d",&n)!=EOF){ for(int i = 1;i <= n;i ++){ scanf("%d",&a[i]); } build(1,n,1); scanf("%d",&q); while(q--){ scanf("%d%d%d",&op,&x,&y); if(op == 1) update(x,y,1,n,1); else printf("%d ",query(x,y,1,n,1)); } } return 0; }
以上是关于hdu 3911 Black And White (线段树 区间合并)的主要内容,如果未能解决你的问题,请参考以下文章
HDU 3911 Black and White (线段树,区间翻转)
[HDOJ3911]Black And White(线段树,区间合并)
HDU 5113--Black And White(搜索+剪枝)