题面:
思路:
首先介绍一下摩尔投票法:
以上截取自博客。我们可以发现摩尔投票法中每个区间记录的num(表示当前区间的绝对众数)和cnt(等于当前区间绝对众数出现次数减去其他数字出现的次数)是可以进行区间合并的,于是我们可以考虑用线段树来维护每个区间的num和cnt,然而这还不够,因为我们需要判断当前区间绝对众数的出现次数是否大于等于threshold,由于arr[i]<=20000,我们可以考虑使用20000个list记录下每个数字出现的下标(注意这是有序的),然后通过二分来计算出当前给定区间中绝对众数的出现次数,到这里就大功告成了。
代码:
class Node:
def __init__(self,l,r):
self.l=l
self.r=r
self.num=-1
self.cnt=0
class SegmentTree:
def __init__(self,arr):
self.a=arr
self.t=list(None for i in range((len(arr)+10)<<2))
self.build(1,0,len(arr)-1)
def pushUp(self,p):
if self.t[p*2].num==self.t[p*2+1].num:
self.t[p].num=self.t[p*2].num
self.t[p].cnt=self.t[p*2].cnt+self.t[p*2+1].cnt
elif self.t[p*2].cnt>self.t[p*2+1].cnt:
self.t[p].num=self.t[p*2].num
self.t[p].cnt=self.t[p*2].cnt-self.t[p*2+1].cnt
else:
self.t[p].num=self.t[p*2+1].num
self.t[p].cnt=self.t[p*2+1].cnt-self.t[p*2].cnt
def build(self,p,l,r):
self.t[p]=Node(l,r)
if l==r:
self.t[p].num=self.a[l]
self.t[p].cnt=1
return
mid=(l+r)>>1
self.build(p*2,l,mid)
self.build(p*2+1,mid+1,r)
self.pushUp(p)
def ask(self,p,l,r):
if self.t[p].l>=l and self.t[p].r<=r:
return copy.copy(self.t[p])
mid=(self.t[p].l+self.t[p].r)>>1
cur=[None]*2
if l<=mid:
cur[0]=self.ask(p*2,l,r)
if r>mid:
cur[1]=self.ask(p*2+1,l,r)
if not cur[0]:
return cur[1]
if not cur[1]:
return cur[0]
ans=Node(-1,-1)
if cur[0].num==cur[1].num:
ans.num=cur[0].num
ans.cnt=cur[0].cnt+cur[1].cnt
elif cur[0].cnt>cur[1].cnt:
ans.num=cur[0].num
ans.cnt=cur[0].cnt-cur[1].cnt
else:
ans.num=cur[1].num
ans.cnt=cur[1].cnt-cur[0].cnt
return ans
class MajorityChecker:
def __init__(self, arr: List[int]):
self.sgt=SegmentTree(arr)
self.buf=list(list() for i in range(20001))
for i in range(len(arr)):
self.buf[arr[i]].append(i)
def query(self, left: int, right: int, threshold: int) -> int:
temp=self.sgt.ask(1,left,right)
l=bisect.bisect_left(self.buf[temp.num],left)
r=bisect.bisect_right(self.buf[temp.num],right)
if r-l>=threshold:
return temp.num
else:
return -1
# Your MajorityChecker object will be instantiated and called as such:
# obj = MajorityChecker(arr)
# param_1 = obj.query(left,right,threshold)