题目
N 个灯泡排成一行,编号从 1 到 N 。最初,所有灯泡都关闭。每天只打开一个灯泡,直到 N 天后所有灯泡都打开。
给你一个长度为 N 的灯泡数组 blubs ,其中 bulls[i] = x 意味着在第 (i+1) 天,我们会把在位置 x 的灯泡打开,其中 i 从 0 开始,x 从 1 开始。
给你一个整数 K ,请你输出在第几天恰好有两个打开的灯泡,使得它们中间 正好 有 K 个灯泡且这些灯泡 全部是关闭的 。
如果不存在这种情况,返回 -1 。如果有多天都出现这种情况,请返回 最小的天数 。
解答
线段树。线段树每个节点维护这个区间内已插入的最左端和最右端节点,初始化为-1。遍历整个数组,设当前数组值为L(0<=L<N),则询问区间[0,L)的最右端已插入节点,[L+1,N)的最左端已插入节点,更新答案,然后在区间中插入节点L。
代码
class Solution {
public:
struct tree{
int l;
int r;
int lmost;
int rmost;
};
vector<tree> t;
void build(int l,int r,int label)
{
t[label].l=l;
t[label].r=r;
t[label].lmost=-1;
t[label].rmost=-1;
if(l<r-1)
{
int mid=(l+r)/2;
build(l,mid,label*2);
build(mid,r,label*2+1);
}
}
int find_lmost(int l,int r,int label)
{
int l1=t[label].l;
int r1=t[label].r;
if(l>=r||l1>=r||l>=r1)
{
return -1;
}
else if(l<=l1&&r1<=r)
{
return t[label].lmost;
}
else
{
int p=find_lmost(l,r,label*2);
if(p!=-1)return p; else return find_lmost(l,r,label*2+1);
}
}
int find_rmost(int l,int r,int label)
{
int l1=t[label].l;
int r1=t[label].r;
if(l>=r||l1>=r||l>=r1)
{
return -1;
}
else if(l<=l1&&r1<=r)
{
return t[label].rmost;
}
else
{
int p=find_rmost(l,r,label*2+1);
if(p!=-1)return p; else return find_rmost(l,r,label*2);
}
}
void insert(int label, int j)
{
int l=t[label].l;
int r=t[label].r;
if(l==r-1)
{
t[label].lmost=l;
t[label].rmost=l;
}
else
{
int mid=(l+r)/2;
if(mid>j)
{
insert(label*2,j);
if(t[label].lmost==-1||t[label].lmost>t[label*2].lmost)
{
t[label].lmost=t[label*2].lmost;
}
if(t[label].rmost==-1||t[label].rmost<t[label*2].rmost)
{
t[label].rmost=t[label*2].rmost;
}
}
else
{
insert(label*2+1,j);
if(t[label].lmost==-1||t[label].lmost>t[label*2+1].lmost)
{
t[label].lmost=t[label*2+1].lmost;
}
if(t[label].rmost==-1||t[label].rmost<t[label*2+1].rmost)
{
t[label].rmost=t[label*2+1].rmost;
}
}
}
}
int kEmptySlots(vector<int>& bulbs, int k) {
int n=bulbs.size();
if(n==0)return -1;
t = vector<tree>(n*20);
build(0,n,1);
for(int i=0;i<n;i++)
{
int j=bulbs[i]-1;
int p=find_rmost(0,j,1);
int q=find_lmost(j+1,n,1);
if(p!=-1)
{
if(j-p==k+1)return i+1;
}
if(q!=-1)
{
if(q-j==k+1)return i+1;
}
insert(1,j);
}
return -1;
}
};