每个闹钟响k秒,给你每个闹钟响的时间,如果响的闹钟数>=m时就会醒来。
求不让小明醒来的最少关闹钟的数量。
POINT:
把闹钟的持续时间[l,r]类似线段树的区间更新一样放入树状数组。
比如他在[1,3]响, 那就在1加1,4减1,那么求2时刻只要求query(2)就行。
然后就一个个贪心的关闹钟,首先排个序。
如果当前i-1这个闹钟的l[i-1]时刻不是k-1个闹钟在响,那么当前i这个闹钟一定可以放,就别搜了,直接放好跳过。
不然就搜一下,看能不能放。从l[i]到r[i-1]搜一下就行。
#include <iostream>
#include <string>
#include <string.h>
#include <math.h>
#include <vector>
#include <map>
#include <stdio.h>
#include <algorithm>
using namespace std;
const int maxn = (2e6+44);
int sum[maxn];
int lowbit(int x)
{
return x&-x;
}
int w,n;
void add(int x,int p)
{
for(int i=x;i<=w;i+=lowbit(i)){
sum[i]+=p;
}
}
int query(int x)
{
int ans=0;
for(int i=x;i>=1;i-=lowbit(i))
{
ans+=sum[i];
}
return ans;
}
int l[maxn];
int main()
{
int m,k;
scanf("%d %d %d",&n,&m,&k);
w=0;
for(int i=1;i<=n;i++){
scanf("%d",&l[i]);
w=max(w,l[i]+m);
}
sort(l+1,l+1+n);
if(k==1){
printf("%d\n",n);
return 0;
}
add(l[1],1);
add(l[1]+m,-1);
int ans=0;
for(int i=2;i<=n;i++){
add(l[i],1);
int flag=1;
if(query(l[i-1])!=k-1){
add(l[i]+m,-1);
continue;
}
for(int j=l[i];j<=l[i-1]+m;j++){
if(query(j)>=k){
flag=0;
ans++;
break;
}
}
if(!flag){
add(l[i],-1);
}
else
add(l[i]+m,-1);
}
printf("%d\n",ans);
}