zoukankan      html  css  js  c++  java
  • 登陆

    还是个水题QwQ
    还是先来一句话题意:给定n个区间[l,r],每个区间在这整段时间内都要独自占用一份资源,求最少几份资源能够满足所有区间

    还是先看数据,第一部分,我还是不知道怎么做,就当是给各路鬼畜做法准备的吧

    解法一:差分+离散化

    没有学过差分的同学请百度一篇博客学一学吧,差分还是个简单的东西的,当然不想学的可以直接跳解法二

    可以想到,差分的套路,每次区间开头,在差分数组++,在区间结尾恰好后一位置,差分数组--。

    那么我们按照序列坐标跑一遍差分数组,即s[i]+=s[i-1],再从中取出差分数组的最大值即可

    大致模拟一下这个过程



    所以最终复杂度就是线性的区间个数加上坐标范围

    但是只能得70%分,因为100%的数据坐标很大啊

    再加上离散化就可以AC了,这里就不再赘述离散化的具体实现了,大家可以自行百度

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define int long long
    using namespace std;
    struct node{
        int l,r;
    }a[100010];
    int n,ans,cnt,mp[200010],tot,s[200010];
    signed main()
    {
        scanf("%lld",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%lld%lld",&a[i].l,&a[i].r);
            mp[++cnt]=a[i].l,mp[++cnt]=a[i].r;
        }
        sort(mp+1,mp+cnt+1);
        cnt=unique(mp+1,mp+cnt+1)-mp-1;
        for(int i=1;i<=n;i++)
        {
            a[i].l=lower_bound(mp+1,mp+cnt+1,a[i].l)-mp;
            a[i].r=lower_bound(mp+1,mp+cnt+1,a[i].r)-mp;
            s[a[i].l]++,s[a[i].r+1]--;
        }
        for(int i=1;i<=cnt;i++)
        {
            s[i]+=s[i-1];
            ans=max(ans,s[i]);
        }
        printf("%lld
    ",ans);
        return 0;
    }



    解法二:贪心

    按照开始进攻的时间把进攻排序

    维护一个数组S,记录当前每个编队安排进去的最后一次打击,最初没有编队

    依次对于每次进攻,扫描数组S,找到任意一个编队,满足当前的进攻开始时间不早于编队的最后一次打击的结束时间。如果这样的编队不存在,则新建一个编队。

    这个贪心算法的时间复杂度是O(n^2),请读者自行证明其正确性。这样就得到了30%

    我们可以用一个小根堆维护每个编队最后一次打击结束的时间,尝试把当前的进攻安排在堆顶(结束时间最早)的编队下。这样时间复杂度就可以降低到O(nlogn)

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<algorithm>
    #define int long long
    using namespace std;
    struct node{
        int l,r,id;
    }a[1000010];
    struct data{
        int id,t;
    };
    priority_queue<data>q;
    int n,ans[1000010],cnt;
    bool cmp(const node &x,const node &y)
    {
        return x.l<y.l;
    }
    bool operator <(const data &x,const data &y)
    {
        return x.t>y.t;
    }
    signed main()
    {
        scanf("%lld",&n);
        for(int i=1;i<=n;i++)
            scanf("%lld%lld",&a[i].l,&a[i].r),a[i].id=i;
        sort(a+1,a+n+1,cmp);
        q.push((data){++cnt,a[1].r}),ans[a[1].id]=cnt;
        for(int i=2;i<=n;i++)
        {
            data u=q.top();
            q.pop();
            if(a[i].l>u.t)
                q.push((data){u.id,a[i].r}),ans[a[i].id]=u.id;
            else
                q.push((data){++cnt,a[i].r}),q.push(u),ans[a[i].id]=cnt;
        }
        printf("%lld
    ",cnt);
        return 0;
    }

    解法三:还是贪心,只是用set维护

    来自@_23333神犇的想法

    按最早进攻时间对进攻排序

    对于每次进攻

    把进攻结束时间之后(即可以下次打击的最早时间)扔进$set$

    每次从set中lower_bound

    如果这之前没有能够继续的编队,就新建一个

    否则用那个继续这次进攻

    #include<bits/stdc++.h>
    #define N 100005
    #define l first
    #define r second
    #define pr pair<int,int>
    #define int long long
    using namespace std;
    
    inline void rd(int &X)
    {
        X=0;int w=0;char ch=0;
        while(!isdigit(ch))w|=ch=='-',ch=getchar();
        while( isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        X=w?-X:X;
    }
    
    int n;
    multiset<int> s;
    multiset<int> :: iterator it;
    pr a[N];
    
    signed main()
    {
        rd(n);
        for(int i=1;i<=n;i++)
            rd(a[i].l),rd(a[i].r);
        sort(a+1,a+1+n);
        s.insert(a[1].r+1);
        for(int i=2;i<=n;i++)
        {
            it=s.upper_bound(a[i].l);
            if(it==s.begin())
                s.insert(a[i].r+1);
            else {
                it--;
                s.erase(it);
                s.insert(a[i].r+1);
            }
        }
        cout<<s.size();
    }
  • 相关阅读:
    测试用例
    web 接口测试入门
    Web 安全测试
    Web 测试总结
    linux的基本操作(NFS服务配置)
    linux的基本操作(mysql 的基本操作)
    linux的基本操作(LNMP的基本操作)
    linux的基本操作(LAMP环境搭建)
    linux 的基本操作(linux系统的日常管理)
    Android官方技术文档翻译——ApplicationId 与 PackageName
  • 原文地址:https://www.cnblogs.com/ivanovcraft/p/9664454.html
Copyright © 2011-2022 走看看