zoukankan      html  css  js  c++  java
  • 线段覆盖的三个题目

     我们可以先对线段进行排序,可能出现如下三种情况

    1不想交

    2相交,不包含

    3相交,包含

    http://tzcoder.cn/acmhome/problemdetail.do?&method=showdetail&id=1532

    http://tzcoder.cn/acmhome/problemdetail.do?method=showdetail&id=5625

    https://www.luogu.com.cn/problem/P1204

    #include<bits/stdc++.h>
    using namespace std;
    struct node
    {
        int L,R;
    }a[5005];
    bool cmp(node a,node b)
    {
        //因为后来相等的关系我其实没有用到
        //不排序也行,我只需要当前的L和R,只要起点最优就可以
        return a.L<b.L;
    }
    int main()
    {
        int n;
        cin>>n;
        for(int i=0;i<n;i++)
            cin>>a[i].L>>a[i].R;
        sort(a,a+n,cmp);
        //排序之后满足起点最优
        //用L表示当前最远的L,用R表示当前最远的R
        int L=a[0].L,R=a[0].R;
        int ans1=0,ans2=0;
        for(int i=1;i<n;i++)
        {
            //这个不满足,对应第二三种,我需要更新我的R
            if(a[i].L<=R)
            {
                //直接取最大R
                R=max(R,a[i].R);
            }
            else
            {
                //以下为不相交,也就是第一种情况
                //至少有一人在挤奶,就是上一次我们统计的那一段
                ans1=max(ans1,R-L);
                //无人挤奶的时间段就是当前的L和上一次的R
                ans2=max(ans2,a[i].L-R);
                //更新L和R
                L=a[i].L;
                R=a[i].R;
            }
        }
        //最后一次有可能是相交了,所以还要更新一次
        ans1=max(ans1,R-L);
        cout<<ans1<<" "<<ans2<<"
    ";
        return 0;
    }
    View Code

    第四个题目需要贪心

    我们可以按照右端点进行排序

    #include <bits/stdc++.h>
    using namespace std;
    struct T
    {
        int l, r, w;
    } a[5005];
    int cmp(T A, T B)
    {
        return A.r < B.r;
    }
    int ans, vis[30005];
    int main()
    {
        int n,h;
        cin>>n>>h;
        for (int i = 0; i < h; i++)
            cin>>a[i].l>>a[i].r>>a[i].w;
        //按照右端点进行排序
        sort(a, a + h, cmp);
        for (int i = 0; i < h; i++)
        {
            int s = 0;
            //看看左边已经有多少个被填了,解决情况3
            for (int j = a[i].l; j <= a[i].r && s < a[i].w; j++)
                if (vis[j])s++;
            //从右向左填,解决剩下的
            //基本思想,少种树,那么就尽力让重合的种上,解决2,3即可
            for (int j = a[i].r; j >= a[i].l && s < a[i].w; j--)
            {
                if (!vis[j])
                {
                    s++,ans++,vis[j] = 1;
                }
            }
        }
        cout<<ans<<"
    ";
        return 0;
    }
    View Code

    直接维护速度并不快,解决区间问题,我们可以使用线段树,但是这个情况2线段树也不行了,所以可以合并一下线段

  • 相关阅读:
    Java
    Java
    Python 浮点数类型的精度问题
    Ubuntu下pip的更新问题
    初章
    第二次结对编程作业
    第一次结对编程作业
    Shengnan的《构建之法》读书笔记
    Backend事后诸葛亮
    ASE Alpha Sprint
  • 原文地址:https://www.cnblogs.com/BobHuang/p/12273406.html
Copyright © 2011-2022 走看看