• HDU 6003 Problem Buyer


    贪心题(好久不做了)

    题解

    考虑最一般的,判断合法性?

    经典贪心问题:左端点升序,左端点相同,右端点降序,c[i]升序

    优先队列,每次选择覆盖x的右端点最小的区间。

    称此方法为“区间匹配贪心”

    最小的k使得任意选k个都能存在“完美匹配”?(虽然这里不用Hall定理)

    对于覆盖了ci的区间设有ti个,那么ans至少是n-ti+1

    一个naive的想法是,ans就是max(n-ti+1)??

    但是可能不止这样,因为存在共用区间的问题

    所以边找ti,边进行之前的贪心匹配。

    这样,到了i,用n-q.size()+1进行更新ans,然后q.pop(),表示用右端点最小的区间匹配上c[i]

    当queue是空的,显然impossible

    考虑有解情况,合法性:

    证明两点:

    1.这样的ans是下界。首先“区间匹配贪心”这样分配是最优的。枚举x相当于最后满足的是哪个,剩下的都选择上。即使有一个可能覆盖了c[i],但是钦定匹配给了别人,

    由于“区间匹配贪心”正确,所以换到c[i]一定不优。这一定是下界。

    2.只要证明存在合法的分配方式,就可以证明ans也是上界。对于一个c[i],虽然可能给了一个ti的区间可能被钦定给了c[i+j]的,但是这样会在c[i+j]的位置统计到。

    由于是取max,所以一定会考虑到!!

    否则显然存在构造方法。

    所以ans也是下界。

    证毕。

    #include<bits/stdc++.h>
    #define reg register int
    #define il inline
    #define fi first
    #define se second
    #define mk(a,b) make_pair(a,b)
    #define numb (ch^'0')
    #define pb push_back
    #define solid const auto &
    #define enter cout<<endl
    #define pii pair<int,int>
    using namespace std;
    typedef long long ll;
    template<class T>il void rd(T &x){
        char ch;x=0;bool fl=false;while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);(fl==true)&&(x=-x);}
    template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');}
    template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');}
    template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('
    ');}
    namespace Modulo{
    const int mod=998244353;
    int ad(int x,int y){return (x+y)>=mod?x+y-mod:x+y;}
    void inc(int &x,int y){x=ad(x,y);}
    int mul(int x,int y){return (ll)x*y%mod;}
    void inc2(int &x,int y){x=mul(x,y);}
    int qm(int x,int y=mod-2){int ret=1;while(y){if(y&1) ret=mul(x,ret);x=mul(x,x);y>>=1;}return ret;}
    template<class ...Args>il int ad(const int a,const int b,const Args &...args) {return ad(ad(a,b),args...);}
    template<class ...Args>il int mul(const int a,const int b,const Args &...args) {return mul(mul(a,b),args...);}
    }
    // using namespace Modulo;
    namespace Miracle{
    const int N=1e5+5;
    int n,m;
    int ans;
    int c[N];
    priority_queue<int,vector<int>,greater<int> >q;
    struct seg{
        int l,r;
        bool friend operator <(seg a,seg b){
            if(a.l==b.l) return a.r>b.r;
            return a.l<b.l;
        }
    }s[N];
    void clear(){
        while(!q.empty()) q.pop();
    }
    int main(){
        int t;rd(t);
        for(reg o=1;o<=t;++o){
            clear();
            rd(n);rd(m);
            for(reg i=1;i<=n;++i){
                rd(s[i].l);rd(s[i].r);
            }
            sort(s+1,s+n+1);
            for(reg i=1;i<=m;++i){
                rd(c[i]);
            }
            sort(c+1,c+m+1);
            int ptr=0;
            int ans=0;
            for(reg i=1;i<=m;++i){
                while(ptr<n&&s[ptr+1].l<=c[i]){
                    if(s[ptr+1].r>=c[i]) q.push(s[ptr+1].r);
                    ++ptr;
                }
                while(!q.empty()&&q.top()<c[i]) q.pop();
                if(q.empty()) {
                    ans=-1;break;
                }
                ans=max(ans,n-(int)q.size()+1);
                q.pop();
            }
            if(ans>=0) printf("Case #%d: %d
    ",o,ans);
            else printf("Case #%d: IMPOSSIBLE!
    ",o);
        }    
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
    */

    鸽巢原理,但是可能不存在合法方案,就现场匹配。

    为了保证最优性,利用“区间匹配贪心”

  • 相关阅读:
    会话追踪技术
    request session application
    Java CAS同步机制 原理详解(为什么并发环境下的COUNT自增操作不安全): Atomic原子类底层用的不是传统意义的锁机制,而是无锁化的CAS机制,通过CAS机制保证多线程修改一个数值的安全性。
    mysql连接拍错总结
    git 从分支上创建一个分支
    linux ---> taskkill pid 8080 /f
    阿里java开发规范 强制约束
    for break
    Mybatis Update操作返回值问题
    springboot 缓存架构
  • 原文地址:https://www.cnblogs.com/Miracevin/p/11000514.html
Copyright © 2020-2023  润新知