小红书2023秋招提前批-精华帖子(双指针或者二分加前缀和)

https://oj.algomooc.com/problem.php?id=5801

小红书的推荐帖子列表为\([0,n)\),其中所有的帖子初始状态为“普通”,现在运营同学把其中的一些帖子区间标记为了“精华”。

运营同学选择了固定长度\(k\),对整个帖子列表截取,要求计算在固定的截取长度k下,能够截取获得的最多精华帖子数量。

输入
第一行输入三个正整数\(n,m,k\),分别代表初始帖子列表长度,精华区间的数量,以及运营同学准备截取的长度。

接下来的m行,每行输入两个正整数\(l_i,r_i\),代表第i个左闭右开区间。

\(1 ≤ k ≤ n ≤ 1000000000\)
\(1 ≤ m ≤ 100000\)
\(0 ≤ l_i < r_i ≤ n\)保证任意两个区间是不重叠的。

输出
一个正整数,代表截取获得的最多的精华帖子数量。
样例输入
5 2 3
1 2
3 5
样例输出
2
提示
这是一个长度为5的帖子列表,如果用0表示普通帖子,1表示精华帖子,则该列表为[0, 1, 0, 1, 1]。 用长度k = 3的区间截取列表,最多能够包含2个精华帖子。

这个帖子列表长度是1e9,所以这个题肯定是枚举帖子个数,而不是枚举帖子长度,所以我们用双指针
下面解释一下代码意思:
这里指的是从[a[l].e+1,.....a[r].e)就已经超过k了,所以l可以不要了

while(a[r].e-a[l].e>k){
	sum-=a[l].e-a[l].s;
	l++;
}

而这里则是需要减去第一个瓷砖块中未被覆盖的瓷砖,也就是下图中蓝色部分,因为sum已经加上了那三块的长度。
image

ans = max(ans, sum - max(0, (a[r].e - k - a[l].s)));
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e6+100;
struct node{
    int s,e;
}a[maxn];
int n,m,k;
int cmp(node x,node y){
    return x.s<y.s;
}
int main(){
    cin>>n>>m>>k;
    for(int i=1;i<=m;i++){
        cin>>a[i].s>>a[i].e;
    }
    sort(a+1,a+m+1,cmp);
    int ans=0,sum=0;
    for(int l=1,r=1;r<=m;r++){
        sum+=(a[r].e-a[r].s);
        while(a[r].e-a[l].e>k){
            sum-=a[l].e-a[l].s;
            l++;
        }
        ans = max(ans, sum - max(0, (a[r].e - k - a[l].s)));
    }
    cout<<ans<<endl;
     
}

这个也可以用前缀和加二分写,https://blog.csdn.net/qq_43406895/article/details/132767517

上面这个题和下面这个题基本一样:
https://leetcode.cn/problems/maximum-white-tiles-covered-by-a-carpet/solutions/1496434/by-endlesscheng-kdy9/

或者看这个解析
https://blog.csdn.net/qq_43406895/article/details/131605543

posted @ 2024-04-26 21:35  lipu123  阅读(288)  评论(0)    收藏  举报