#4617. 逛公园

题目描述

小凯做题做累了,他想去逛公园。

公园里有 $m$ 个亲子项目,每个项目一天只能一个家庭参加。一共有 $n$ 个家庭,第 $i$ 个家庭希望在第 $l_i$ 到 $r_i$ 天内参加恰好一次第 $p_i$ 个项目。但是公园的工作人员很懒,他们希望上班的天数尽量少。某天要上班当且仅当至少有一个家庭参加了任意一个项目。

工作人员看到了小凯,想让他帮忙使得工作人员有更多咕咕咕的机会。但小凯又双叒叕不会了,所以他请你求出这个最少的上班时间。如果无论如何安排都不能达到要求,输出 GG。

数据范围

$n \le 10^5, l,r,m \le 10^9$

题解

挺妙又难写的一道贪心题。

考虑每种类型能否满足,考虑到如果右端点都不同的话,那每个区间都取右端点就好了,于是考虑右端点相同的情况,那我们先让左端点最大的区间先确定这个右端点,剩下区间右端点左移即可,这样我们就可以把一个类型的区间的右端点变得互不相同。

考虑多个类型,首先我们先找到一个还没确定的区间中右端点最小的那个,那对于剩下的类型,如果存在左端点大于等于这个右端点的,那可以把这个区间确定在这个右端点上,如果有多个区间同时满足,根据贪心应该让右端点最小的被确定。

具体实现有点复杂(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;
}

 

posted @ 2019-11-06 19:23  xjqxjq  阅读(138)  评论(0编辑  收藏  举报