题目大意:
给出直线上N个点的位置和颜色(0或1),求最大的区间,使得区间内0的个数大于等于1的个数且0的个数减去1的个数为偶数。
解题过程:
1.先贴个lsdsjy大牛的线段树的做法:http://www.cnblogs.com/lsdsjy/p/4032614.html
2.这题一个非常巧妙的转换是:由于0的个数减去1的个数为偶数,那么区间内的点的个数只能是偶数,这样只要枚举左开右闭区间
(L,R], R和L位置的奇偶性相同。 所以只要分2次做,奇数位的和偶数位的单独拿出来。
下面仅讨论L,R都是偶数的情况。
用A[i]表示前i个数1有多少个,B[i]表示前i个数0有多少。
一个区间(L,R]符合要求必须满足A[R]-A[L]>=B[R]-B[L] -> A[R]-B[R] >= A[L]-B[L]
令K[i]=A[i]-B[i] -> K[R] >= K[L]
方法一(单调队列):
如果一个有K[i],K[j]满足i<j && K[i]<=K[j] 那么选取区间的L端点的时候肯定是选i比较优。
所以可以维护一个单调队列,只有当新的K[i]<K[tail] 的时候 才加入队列。
然后枚举右端点R,只要在单调队列中二分找到一个最小的i,满足K[i]<=K[R],那么以R为右端点的最优区间就是(i,R].
方法二(动态规划):
这种方法不必分奇偶讨论,非常巧妙.
F[i]表示满足K[t]=i 的最小的t. g[i]=min{f[i],f[i-2],f[i-4]....}. 因为每次相差的都是二,可以保证0,1的个数奇偶性相同。
枚举右端点R,如果g[K[R]]<R,那么以R为右端点的最优区间就是( g[K[R]] , R] .