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,,再去判断它合不合法

实际代码:

c++ 复制代码
#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;
}

限制:

  • 1 <= intervals.length <= 105
  • 1 <= queries.length <= 105
  • intervals[i].length == 2
  • 1 <= lefti <= righti <= 107
  • 1 <= queries[j] <= 107
相关推荐
.Vcoistnt9 分钟前
Codeforces Round 994 (Div. 2)(A-D)
数据结构·c++·算法·贪心算法·动态规划
ALISHENGYA34 分钟前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(实战训练三)
数据结构·c++·算法·图论
Dream it possible!3 小时前
LeetCode 热题 100_LRU 缓存(35_146_中等_C++)(哈希表 + 双向链表)(构造函数声明+初始化列表=进行变量初始化和赋值)
c++·leetcode·缓存
我码玄黄3 小时前
正则表达式优化之算法和效率优化
前端·javascript·算法·正则表达式
Solitudefire3 小时前
蓝桥杯刷题——day9
算法·蓝桥杯
三万棵雪松4 小时前
1.系统学习-线性回归
算法·机器学习·回归·线性回归·监督学习
Easy数模4 小时前
基于LR/GNB/SVM/KNN/DT算法的鸢尾花分类和K-Means算法的聚类分析
算法·机器学习·支持向量机·分类·聚类
2401_858286115 小时前
117.【C语言】数据结构之排序(选择排序)
c语言·开发语言·数据结构·笔记·算法·排序算法
thesky1234565 小时前
活着就好20241226
学习·算法
td爆米花5 小时前
C#冒泡排序
数据结构·算法·排序算法