zoukankan      html  css  js  c++  java
  • #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;
    }
  • 相关阅读:
    测试打印功能
    绘图
    图片验证码
    图片防盗
    图片水印
    surface 译
    ViewManager 译
    WindowId 译
    Display
    LayoutParams
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/11807523.html
Copyright © 2011-2022 走看看