emmm…考试周一天一套小白月赛保持手感…
别问为什么,怕被太难的题卡的挂科…
本来不想写什么题解,不过这题确实有妙处,就记录一下吧
题目大意:
为了抵御深渊的蔓延,被深渊毁掉家园的人们组建法兰不死队来镇压深渊。已知法兰不死队的最大编制为 k k k,即队伍最多能有 k k k人。有 n n n个人想加入不死队,他们每人都有一个期望入伍时间 s s s和退役时间 t t t。入伍时间表示这个人如果要入伍的话只能在 s s s时刻入伍。退役时间代表这个人可以在t时刻后退伍。因为战况严峻,所以队伍必须一直保持达到最大编制的状态。即队伍达到最大编制时候,队伍里有人可以退役的话,如果没有人来接替这个人的位置就不能退役。问最少有多少人没有进入法兰不死队的经历。
注:同一时刻,允许多个人一起入伍或者退伍,退伍时间要严格大于 t t t
该人是否入伍是你来决定的 即就算没达到最多编制人数 k k k,到了某人的入伍时间,你可以选择不让他入伍
题目思路:
按照题解所说,可以抽象一下:
选出最多的线段,使的数轴上的每个点被线段覆盖不超过k次
可以把线段覆盖想成区间覆盖问题,当前点被哪些线段覆盖到。之后,可以把以该点作为起点的线段放进到扫描线组成的集合里,但是放入的过程中要考虑一下,如果当前点覆盖超过k次了,应该让哪个线段出去,贪心的考虑,一定会让结束时间大的先出去,因为会减少后面空间的浪费,既然出去了,那么这个就不会入伍
了,也就可以记录答案了。
贪心的好题(G)
Code:
/*** keep hungry and calm CoolGuang! ***/
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define dl(x) printf("%lld\n",x);
#define di(x) printf("%d\n",x);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll INF= 1e17+7;
const ll maxn = 1e6+700;
const ll mod= 1e4+7;
const double PI = acos(-1);
template<typename T>inline void read(T &a){
char c=getchar();T x=0,f=1;while(!isdigit(c)){
if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){
x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll n,m,p;
multiset<ll>s;
vector<int>v[maxn];
int main(){
read(n);read(m);
for(int i=1;i<=n;i++){
int x,y;read(x);read(y);
v[x].push_back(y);
}
int ans = 0;
for(int i=1;i<=1000000;i++){
while(s.size()&&*s.begin() < i) s.erase(s.begin());
for(int x:v[i]){
if(s.size() < m) s.insert(x);
else{
ans ++;
s.insert(x);
s.erase(--s.end());
}
}
}
printf("%d\n",ans);
return 0;
}
/***
5 2
19186 25985
51782 55585
25373 58921
59901 64624
43221 67137
***/