题意:有 \(n\) 个讲师,对于讲师 \(i\),他可以在 \([l_i,r_i]\) 中选一天讲课,问对于 \(x \in [1,n]\),有多少连续的 \(x\) 天可以做到都有讲师讲课。
先考虑区间的 \(l\) 互不相同时如何解决。
对于已知的 \([l,r]\) 是否存在完美匹配,判断是简单的,我们贪心地按天数从左往右依次解决,每次填覆盖当前天的 \(r\) 最小的讲师即可。
根据 hall 定理,我们发现若 \([l,r]\) 满足条件,那么 \([nl,nr] \subseteq [l,r]\) 必然满足条件,所以我们只需要判断 \([l,r]\) 是否满足条件即可。
然后我们从后往前扫求对于第 \(i\) 天,符合条件的最大的 \(R_i\) 在哪里就行了,这个根据上面的贪心处理即可。
那么对于区间 \(l\) 有相同的其实差不多,若区间 \([l,r]\) 被分配给了第 \(d\) 天,那这个区间可以被写成 \([d,r]\),然后就和区间的 \(l\) 互不相同的时候一样了。
点击查看代码
#include<bits/stdc++.h>
#define fir first
#define sec second
#define int long long
#define lowbit(x) x&(-x)
#define mkp(a,b) make_pair(a,b)
using namespace std;
typedef pair<int,int> pir;
inline int read(){
int x=0,f=1; char c=getchar();
while(!isdigit(c)){if(c=='-') f=-1; c=getchar();}
while(isdigit(c)){x=x*10+(c^48); c=getchar();}
return x*f;
}
const int inf=1e9,N=2e5+5;
int n,m;
vector<int> ed[N];
multiset<int> s;
int c[N],nc[N],op[N],pos[N],res[N];
signed main(){
n=read();
for(int i=1;i<=n;i++){
int l=read(),r=read();
ed[l].push_back(r);
m=max(m,r);
}
for(int i=1;i<=m;i++){
for(auto r:ed[i]) s.insert(r);
while(s.size()&&*s.begin()<i) s.erase(s.begin());
if(s.size()){
int r=*s.begin();
s.erase(s.begin());
c[i]++,c[r+1]--;
op[i]=1;
}
else nc[i]++;
}
for(int i=1;i<=m;i++) nc[i]+=nc[i-1],c[i]+=c[i-1];
int r=m+1;
for(int i=m;i>=1;i--){
int num=c[i]-op[i]+1+nc[i-1];
pos[nc[i]]=i;
if(num<=m&&pos[num]) r=min(r,pos[num]);
res[r-i]++;
}
for(int i=n;i;i--) res[i]+=res[i+1];
for(int i=1;i<=n;i++) cout<<res[i]<<'\n';
}