题目描述
小凯做题做累了,他想去逛公园。
公园里有 m m m 个亲子项目,每个项目一天只能一个家庭参加。一共有 n n n 个家庭,第 i i i 个家庭希望在第 l i l_i li 到 r i r_i ri 天内参加恰好一次第 p i p_i pi 个项目。但是公园的工作人员很懒,他们希望上班的天数尽量少。某天要上班当且仅当至少有一个家庭参加了任意一个项目。
工作人员看到了小凯,想让他帮忙使得工作人员有更多咕咕咕的机会。但小凯又双叒叕不会了,所以他请你求出这个最少的上班时间。如果无论如何安排都不能达到要求,输出 GG。
数据范围
n ≤ 1 0 5 , l , r , m ≤ 1 0 9 n \le 10^5, l,r,m \le 10^9 n≤105,l,r,m≤109
题解
挺妙又难写的一道贪心题。
考虑每种类型能否满足,考虑到如果右端点都不同的话,那每个区间都取右端点就好了,于是考虑右端点相同的情况,那我们先让左端点最大的区间先确定这个右端点,剩下区间右端点左移即可,这样我们就可以把一个类型的区间的右端点变得互不相同。
考虑多个类型,首先我们先找到一个还没确定的区间中右端点最小的那个,那对于剩下的类型,如果存在左端点大于等于这个右端点的,那可以把这个区间确定在这个右端点上,如果有多个区间同时满足,根据贪心应该让右端点最小的被确定。
具体实现有点复杂(STL大法好)。
代码
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m,t,ans,fl[N];
struct O{
int l,r,x;
friend bool operator < (const O& A,const O& B){
return A.l<B.l;
}
}p[N];
struct S{
int l,r,x,i;
friend bool operator < (const S& A,const S& B){
return A.r<B.r;
}
};
multiset<S>s;
priority_queue<O>q;
priority_queue<S>d[N];vector<O>e[N];
queue<int>h,H;
bool cmp(O A,O B){
return A.x!=B.x?A.x<B.x:A.r>B.r;
}
int main(){
cin>>n>>m;
for (int i=1,l,r,x;i<=n;i++)
scanf("%d%d%d",&l,&r,&x),
p[i]=(O){l,r,x};
sort(p+1,p+n+1,cmp);
for (int i=1,j=0,r;i<=n;i=j+1){
while(j<n && p[j+1].x==p[i].x) j++;
t++;r=0;for (int k=i;k<=j;k++)
p[k].x=t,r=max(p[k].r,r);
for (int k=r,c=i;;k--){
if (q.empty()) k=p[c].r;
while(c<=j && p[c].r==k)
q.push(p[c]),c++;
if (!q.empty()){
O u=q.top();u.r=k;q.pop();
if (u.r<u.l) return puts("GG"),0;
e[u.x].push_back(u);
}
if (c>j && q.empty()) break;
}
}
for (int i=1,z,j=0;i<=t;i++){
z=e[i].size();
sort(e[i].begin(),e[i].end());
for (int k=0;k<z;k++) p[++j]=e[i][k];
}
sort(p+1,p+n+1);
for (int i=1;i<=n;i++)
s.insert((S){p[i].l,p[i].r,p[i].x,i});
for (int j=0,i;!s.empty();){
S u=(*s.begin());ans++;s.erase(s.begin());fl[u.i]=1;
while(j<n && p[j+1].l<=u.r){
j++;if (fl[j]) continue;
if (d[i=p[j].x].empty()) h.push(i);
d[i].push((S){p[j].l,-p[j].r,p[j].x,j});
}
while(!h.empty()){
int x=h.front();h.pop();
while(!d[x].empty())
if (fl[d[x].top().i]) d[x].pop();
else break;
if (d[x].empty()) continue;
if (x==u.x){H.push(x);continue;}
S v=d[x].top();v.r=-v.r;d[x].pop();
s.erase(s.find(v));fl[v.i]=1;H.push(x);
}
h=H;while(!H.empty()) H.pop();
}
cout<<ans<<endl;return 0;
}