常见优化技巧——Diamond Collector S

[USACO16OPEN] Diamond Collector S

题目描述

Bessie the cow, always a fan of shiny objects, has taken up a hobby of mining diamonds in her spare time! She has collected N N N diamonds ( N ≤ 50 , 000 N \leq 50,000 N50,000) of varying sizes, and she wants to arrange some of them in a pair of display cases in the barn.

Since Bessie wants the diamonds in each of the two cases to be relatively similar in size, she decides that she will not include two diamonds in the same case if their sizes differ by more than K K K (two diamonds can be displayed together in the same case if their sizes differ by exactly K K K). Given K K K, please help Bessie determine the maximum number of diamonds she can display in both cases together.

奶牛Bessie很喜欢闪亮亮的东西(BalingBaling),所以她喜欢在她的空余时间开采钻石!她现在已经收集了N颗不同大小的钻石(N<=50,000),现在她想在谷仓的两个陈列架上摆放一些钻石。

Bessie想让这些陈列架上的钻石保持相似的大小,所以她不会把两个大小相差K以上的钻石同时放在一个陈列架上(如果两颗钻石的大小差值不大于K,那么它们可以同时放在一个陈列架上)。现在给出K,请你帮Bessie确定她最多一共可以放多少颗钻石在这两个陈列架上。

输入格式

The first line of the input file contains N N N and K K K ( 0 ≤ K ≤ 1 , 000 , 000 , 000 0 \leq K \leq 1,000,000,000 0K1,000,000,000).

The next N N N lines each contain an integer giving the size of one of the

diamonds. All sizes will be positive and will not exceed 1 , 000 , 000 , 000 1,000,000,000 1,000,000,000.

输出格式

Output a single positive integer, telling the maximum number of diamonds that

Bessie can showcase in total in both the cases.

样例 #1

样例输入 #1

7 3
10
5
1
12
9
5
14

样例输出 #1

5

思路

  • 这道题目有两个陈列架,所以找出一个最大的是不行的,而且找出次大的和最大的加起来也是不可行的,因为不保证最大和次大的区间不重叠,所以可以正序扫一遍然后找出到每一个点之前最长的差小于等于k的序列然后再倒序找一遍找出到每一个点之后最长的差小于等于k的序列,细节:在某点之前和之后是不包括自己的,排序完了之后一般双指针无需写限制条件对于两个陈列架之类的题,我们可以分成两部分来进行维护k区间的方法

代码

#include<iostream>
#include<algorithm>
#include<unordered_map>

using namespace std;

typedef long long LL;

const int N = 1e6+10;
//题目有两个陈列架
int w[N];
int n,m,k;
int q[N],h[N];

int main(){
    cin>>n>>k;
    for(int i=1;i<=n;i++){
        cin>>w[i];
    }
    
    sort(w+1,w+1+n);
    int res=0;
    q[1]=h[1]=1;
    for(int i=2,j=1;i<=n;i++){
        while(w[i]-w[j]>k)j++;//一般排好序后不需要写限制条件
        q[i]=max(q[i-1],i-j+1);
    }
    //第二个陈列架
    for(int i=n-1,j=n;i>=1;i--){
        while(w[j]-w[i]>k)j--;
        h[i]=max(h[i+1],j-i+1);
    }
    
    
    for(int i=1;i<n;i++){
        res=max(res,h[i+1]+q[i]);
    }
    cout<<res;
    
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

green qwq

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值