D. Buying gifts

文章讲述了在Codeforces上的一个问题D的解决方法,作者首先介绍了自己对问题的理解,通过结构体排序和二分查找策略来优化选择过程。然后,作者提到了看过马哥的代码后,理解到可以使用从小到大排序,结合后缀最大值进行剪枝优化。在实现过程中遇到了编译问题,但学习到了set的二分查找功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:Problem - D - Codeforces

主要思路:

我自己的思路,使用结构体然后按a店从大到小排序,然后一个人买的东西从大到小然后从前往后如果选了最大的那第二个人剩下的二分找最接近这个的,后面b店可以随便选,如果遇到大的可以不选b店去选a店。然后在第二个大的此时对应的那个最大的那个b店里的东西是肯定要买的,这时候就要开始考虑了,是否还可以用二分的那个数,然后在二分找到最接近第二大的那个数然后在和之前必须买的最大的数比较然后再找最小值。

看了马哥代码后的思路:a店从小到大排序然后一开始set里面是空的然后,排好序后用b点后缀最大求出每个位置后的最大值,然后是从a点从小遍历就是全买后面的b,然后用后缀最大值剪当前的a,然后st是加可以选择买不买的b店,然后后面在判断二分st里面在a店价值左右两个知否比后缀最大大,大的话就可以在更新最小值。

然后我的思路好像是写起来有点麻烦的,因为对于移除st里面数据的时候还要判断是否后面还有这个数据所以应该是要用mp记录是否次数为0或者得用multiset。

#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <map>
#include <queue>
#include <stack>
#include <set>
#include<vector>
#include<cstdio>
typedef long long ll;
using namespace std;
struct hh{
    ll x,y;
};
int cmp(hh l,hh r){
    if(l.x==r.x)return l.y>r.y;
    return l.x<r.x;
}
ll pm[5000010];
pair<ll,ll>a[5000010];
void solve(){
    set<ll>st;  
    ll n;
    scanf("%lld",&n);
    for(int i=1;i<=n;i++){
        cin>>a[i].first;
        cin>>a[i].second;
        //cin>>a[i].x;
        //cin>>a[i].y;
    }
    sort(a+1,a+n+1);
    pm[n+1]=-1e18;
    st.insert(1e10);
    for(int i=n;i>=1;i--){
        pm[i]=max(pm[i+1],a[i].second);
    }
    ll mi=0x3f3f3f3f;
    for(int i=1;i<=n;i++){
        if(st.size()){
            set<ll> :: iterator t;
            t=st.lower_bound(a[i].first);
            if(*t>=pm[i+1]) mi=min(mi,abs(a[i].first-*t));
            t--;
            if(*t>=pm[i+1]) mi=min(mi,abs(a[i].first-*t));
        }
        mi=min(mi,abs(a[i].first-pm[i+1]));
        st.insert(a[i].second);
    }
    cout<<mi<<endl;
}
int main()
{   

    ll t;
    cin>>t;
    while (t--)
    {
        solve();
    }
}

这题狂wa30多次所以一定要寄录下来,人麻了。但是也学到一些东西,比如set里面二分函数如果没有比他大的话会返回end()。

这题最后还没a是因为编译器问题,真是人麻了拉黑20版的编译器....

 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值