2023-07-18力扣每日一题-有点难

这篇具有很好参考价值的文章主要介绍了2023-07-18力扣每日一题-有点难。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

链接:

1851. 包含每个查询的最小区间

题意:

给定一个区间二维数组,有N个[L,R]区间(闭区间)

给定一组查询,有M个正整数,求存在于区间数组中的最小R-L+1满足L<=M[i]<=R

解:

本来看标签有个扫描线,想写个差分,然后排序查询整O(1)查询的,没写出来QWQ,也不知道有没有这种整法

优先队列倒是会写

因为每个查询独立且一次性给出,所以可以离线查询,对查询数组从小到大排序(记得保留原序),称为NM

对于一个左端点L小于NM[i]的区间,对于NM[i]以及其后面的查询都是可能合法的区间,因为NM递增

对于一个右端点R小于NM[i]的区间,对于NM[i]以及其后面的查询都是一定非法的区间,因为NM递增

所以当查询从小到大时,L若从小到大,则对于这个查询合法则对后面的所以查询皆合法,R若从小到大,则对这个查询非法则对后面的所以查询皆非法

那么步骤就是,排序区间数组和查询数组,双指针遍历,对于每个查询:

将所有NM[i]>=L,加入一个容器,即步骤1,得到一个所有可能合法区间

将容器内所有NM[i]>R,剔除,即步骤2,可以得到一个该值的所有一定合法区间

最后选择容器中最小R-L+1,得到该查询的答案。难点就在于在这个容器中删除NM[i]>R

这时候就要使用我们的优先队列了,使小的R-L+1在前面,在这基础上,小的R在前面(由于L都是合法的所以不需要存L)

这时候只要不断删除顶部非法的R,就可以得到最小的R-L+1,然后我这边用map存了答案,遍历一遍原序,访问map拿答案

OA:为什么不是先排序R再排序R-L+1

​ 因为假设[1,7] [2,7] [6,8] ,对于查询7来说选择[4,8] 是最好的,找最小的R-L+1才是优先,不过同样的,如果是查询8,按照我们先R-L+1再R的顺序排序[6,8] [2,7] [1,7] [6,8]直接就是最好的,会有非法的R残留,不过重点是找最小的合法的R-L+1,优先提供最小的R-L+1,,再去判断它合不合法

实际代码:

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
/*
bool cmp1(const PII& L,const PII& R)//自定义排序函数 
{
    if(L.first==R.first) return L.second>R.second; 
    else return L.first>R.first; 
}*/
struct cmp1//自定义排序类 
{
    bool operator() (const PII& L,const PII& R)
    {
        if(L.first==R.first) return L.second>R.second; 
        else return L.first>R.first; 
    }
};
vector<int> minInterval(vector<vector<int>>& intervals, vector<int>& queries)
{
    vector<int> q=queries;//拷贝-原序 
    //priority_queue<PII,vector<PII>,decltype(&cmp1)>p_q(cmp1); //函数式自定义优先队列 
    priority_queue<PII,vector<PII>,cmp1>p_q;//类式自定义优先队列 
    //优先队列 小距离优先 小右端点优先 
    map<int,int>mtp;//非原序存储答案 
    
    sort(queries.begin(),queries.end());
    sort(intervals.begin(),intervals.end());
    
    int left=0,lg=intervals.size();
    for(auto querie:queries)
    {
        while(left<lg && intervals[left][0]<=querie)//左端点符合 - 步骤1
        {
            p_q.push({intervals[left][1]-intervals[left][0]+1,intervals[left][1]});
            left++;
        }
        while(!p_q.empty() && p_q.top().second<querie)//右端点不符合 - 步骤2
        {
            p_q.pop(); 
        }
        if(!p_q.empty()) mtp[querie]=p_q.top().first;
    }
    
    for(auto &iq:q)
    {
        if(mtp[iq]==0) mtp[iq]=-1;
        iq=mtp[iq];
    }
    
    return q;
}
int main()
{
    int n;cin>>n;
    vector<vector<int>> intervals;
    vector<int> queries;
    for(int i=1;i<=n;i++)
    {
        int a,b;cin>>a>>b;
        vector<int>temp{a,b};
        intervals.push_back(temp);
    }
    while(cin>>n)
    {
        queries.push_back(n);
    }
    vector<int>ans=minInterval(intervals,queries);
    for(auto i:ans)
    {
        cout<<i<<" ";
    }
    cout<<endl;
    return 0;
}

限制:文章来源地址https://www.toymoban.com/news/detail-599061.html

  • 1 <= intervals.length <= 105
  • 1 <= queries.length <= 105
  • intervals[i].length == 2
  • 1 <= lefti <= righti <= 107
  • 1 <= queries[j] <= 107

到了这里,关于2023-07-18力扣每日一题-有点难的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 2023-07-11力扣每日一题

    链接: https://leetcode.cn/problems/maximum-alternating-subsequence-sum/ 题意: 给定一个数组,求一个子序列,使这个子序列的 奇数位和-偶数位和 最大(下标从1开始的话|反正第一个数是+) 解: 找下坡,曲折处两个分下坡大于一个总下坡(如图) 实际代码: 思维: DP?: 限制: 1 = nu

    2024年02月15日
    浏览(58)
  • 2023-07-15力扣每日一题

    链接: 18. 四数之和 题意: 一个数组n,一个目标值t,在数组内找四个数字和等于t,求能有多少种组合 解: 0716:一看怎么昨天卡没打,原来昨天做的第一题不是每日一题,麻了 n很小,200,那么 先排序 ,然后弄一个 双指针开双循环 l,r ,确定每个组合的最大数字-数字4和最

    2024年02月16日
    浏览(38)
  • 2023-09-07力扣每日一题

    链接: [2594. 修车的最少时间](https://leetcode.cn/problems/form-smallest-number-from-two-digit-arrays/) 题意: 一个能力R的人R*N*N分钟修N辆车,求最快多久修完(多人多车) 解: 二分很好想,主要是怎么检查(数学废物润去看题解了) 实际代码: 限制: 1 = ranks.length = 105 1 = ranks[i] = 100 1 = ca

    2024年02月09日
    浏览(37)
  • 2023-07-14力扣每日一题

    链接: 979. 在二叉树中分配硬币 题意: 一个二叉树,n个节点,节点 权值总和 为n, 每次 可以 相邻节点 间移动 1 权值 求让每个节点都为1的最少次数 解: 给定了一个树的结构体,先整一手DFS/BFS,n不大,随便莽莽 首先每个节点只需要剩下1,而且可以知道 叶子节点 如果不

    2024年02月16日
    浏览(35)
  • 2023-07-26力扣每日一题-区间翻转线段树

    链接: 2569. 更新数组后处理求和查询 题意: 给两个等长数组nums1和nums2,三个操作: 操作1:将nums1的 [l,r] 翻转(0变1,1变0) 操作2:将 nums2[any] 变成 nums2[any]+nums1[any]*p ,p由操作给出,any表示数组里的每一位 操作3:查询nums2的和 解: 由于每次更新nums2的时候,不需要考虑

    2024年02月15日
    浏览(38)
  • 2023-08-18力扣每日一题

    链接: 1388. 3n 块披萨 题意: 一个长度3n的环,选n次数字,每次选完以后相邻的数字会消失,求选取结果最大值 解: 这波是~~(ctrl)CV工程师了~~ 核心思想是选取 n个不相邻 的元素一定 合法 ,我推不出来,猜一猜倒是可以O.o DP[i][j] 表示从 [0,i] 中选取 j 个数字的最大值 初始

    2024年02月12日
    浏览(62)
  • 2023-07-07 LeetCode每日一题(过桥的时间)

    点击跳转到题目位置 共有 k 位工人计划将 n 个箱子从旧仓库移动到新仓库。给你两个整数 n 和 k,以及一个二维整数数组 time ,数组的大小为 k x 4 ,其中 time[i] = [leftToRighti, pickOldi, rightToLefti, putNewi] 。 一条河将两座仓库分隔,只能通过一座桥通行。旧仓库位于河的右岸,新仓

    2024年02月15日
    浏览(37)
  • 2023-07-31 LeetCode每日一题(重排链表)

    点击跳转到题目位置 给定一个单链表 L 的头节点 head ,单链表 L 表示为: 请将其重新排列后变为: 不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。 示例 1: 示例 2: 提示: 链表的长度范围为 [1, 5 * 10 4 ] 1 = node.val = 1000 (1) 使用 分治 的思路来解决问题。

    2024年02月14日
    浏览(45)
  • 2023-07-08 LeetCode每日一题(三数之和)

    点击跳转到题目位置 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请 你返回所有和为 0 且不重复的三元组。 **注意:**答案中不可以包含重复的三元组。 提示: 3 = nums.length = 3000 -10 5

    2024年02月13日
    浏览(49)
  • 2023-07-29 LeetCode每日一题(环形链表)

    点击跳转到题目位置 给你一个链表的头节点 head ,判断链表中是否有环。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:p

    2024年02月15日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包