链接
https://nanti.jisuanke.com/t/28880
题解
当时比赛的时候写了个随机化暴力用来对拍QwQ
这题就是贪心,先按照做短点从大到小排序,再按照右端点从小到大排序,然后进行模拟就好了
问题在于如何模拟?
最暴力的方式就是开一个数组,涵盖每一个时间点,每次选择了新任务就把对应的所有时间点上的计数器+1,查看一个任务能否被执行,就扫描这段区间,看看最大值是不是等于
k
k
,如果等于说明此任务无法执行
首先时间不允许,其次
x,y≤109
x
,
y
≤
10
9
,这么大的数组也开不下,那就离散啊,然后再用分块或者线段树不就好了,为了图方便,我写的分块
代码
#include <cstdio>
#include <cctype>
#include <algorithm>
#include <cstring>
#include <queue>
#include <cmath>
#define lowbit(x) (x&-x)
#define maxn 200010
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
struct video
{
int x, y;
bool operator<(video a){return x==a.x?y<a.y:x>a.x;}
}v[maxn];
int now, ans, n, k, list[maxn], cnt[maxn], block[maxn], bmax[maxn], tag[maxn];
int read(int x=0)
{
char c, f=1;
for(c=getchar();!isdigit(c) and c^-1;c=getchar())if(f=='-')f=-1;
for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-48;
return f*x;
}
int ls(int x)
{
return lower_bound(list+1,list+*list+1,x)-list;
}
void init()
{
int i, x, y, size, t=0;
n=read(), k=read();
for(i=1;i<=n;i++)v[i].x=read(), v[i].y=read()-1, list[++*list]=v[i].x, list[++*list]=v[i].y;
sort(v+1,v+n+1);
sort(list+1,list+*list+1);
for(i=1;i<=*list;i++)if(list[i]!=list[i-1] or i==1)list[++t]=list[i];
*list=t;
for(i=1;i<=n;i++)v[i].x=ls(v[i].x), v[i].y=ls(v[i].y);
size=sqrt(*list);
for(i=1;i<=*list;i++)block[i]=i/size;
}
void segadd(int a, int b)
{
int i;
for(i=block[a]+1;i<block[b];i++)tag[i]++;
for(i=a;block[i]==block[a] and i<=b;i++)cnt[i]++, bmax[block[a]]=max(bmax[block[a]],cnt[i]);
if(block[a]^block[b])for(i=b;block[i]==block[b] and i>=a;i--)cnt[i]++, bmax[block[b]]=max(bmax[block[b]],cnt[i]);
}
int segmax(int a, int b)
{
int i, t=-1;
for(i=block[a]+1;i<block[b];i++)t=max(t,tag[i]+bmax[i]);
for(i=a;block[i]==block[a] and i<=b;i++)t=max(t,tag[block[a]]+cnt[i]);
if(block[a]^block[b])for(i=b;block[i]==block[b] and i>=a;i--)t=max(t,tag[block[b]]+cnt[i]);
return t;
}
void solve()
{
int i;
for(i=1;i<=n;i++)
{
if(segmax(v[i].x,v[i].y)<k)
{
segadd(v[i].x,v[i].y);
ans++;
}
}
}
int main()
{
init();
solve();
printf("%d",ans);
return 0;
}