HDU(6695)2019杭电多校第十场1005

本文介绍了一道竞赛题目,通过使用STL库中的multiset和set来解决两个列表中最大值的最小值问题。文章详细解释了multiset的用法及如何优化算法至nlogn级别。

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

HDU(6695)2019杭电多校第十场1005(某某大佬的STL练习题)

题意:给你几对点,其中每一对必须选一个点,问两个列的最大值的最小值是多少。这称为a,b列。

题解:多个STL库混着用就完事了。
A:把b列的所有值都放到multiset中(set不能放重复值,这个可以)
B:根据a列的值sort从小到大一下,然后遍历一下,把之前的值都放在一个SET中。
C:在遍历的过程中,每一次循环删除之前的a对应的b,并找出剩下的最大值,为接下来的比较做准备。

multiset的用法
构造 multiset Mul;
插入 Mul.insert();
查找 Mul.find(string);
查找失败 返回值为Mul.end(),查找成功后,返回下标
迭代器 multiset::iterator it;可用作遍历集合,*it是元素,it是位置
删除 Mul.erase(it),一般就是删除find出来的it
剩下的和set一样。只是可以存重复数据而已,注意一点:multiset的删除erease,会把所有的相同的元素都删除

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mx = 3e5 + 7;
const ll wa = 8e9 + 7;
struct node {
    ll a, b;
} z[mx];
ll reb[mx];
bool cmp(node a, node b) {
    return a.a < b.a;
}

int main() {
    ios_base::sync_with_stdio(false);
#ifdef ACM_LOCAL
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    int t;
    cin>>t;
    multiset<ll>cry;
    set<ll> se;
    while (t--){
        int n;
        cin>>n;
        ll ma = -1;
        for (int i=1;i<=n;i++){
            cin>>z[i].a>>z[i].b;
            reb[i] = z[i].b;
            ma = max(reb[i],ma);
            cry.insert(z[i].b);
        }
        sort(z+1,z+1+n,cmp);
        sort(reb+1,reb+1+n);
        int cn = 0;
        set<ll>::iterator it;
        multiset<ll>::iterator tt;
        reb[0] = 0;
        ll ans = 7e18+7;
        for (int i=1;i<=n;i++){
            tt = cry.find(z[i].b);
            cry.erase(tt);
            tt = cry.end();
            ma = -1;
            ll tmp = 7e18+7;
            if (!cry.empty()) {
                tt--, ma = *tt;
                tmp = abs(z[i].a - ma);
            }
            if (!se.empty()) {
                 it = se.lower_bound(z[i].a);
                 it--;it--;it--,it--;
                 for (int j=1;j<=8;j++,it++){  //把最近周围的8个数都遍历一遍,玄学过题。
                     ll re = *it;
                     if (*it>ma&&it!=se.end())
                         tmp = min(tmp,abs(z[i].a - *it));
                 }
            }
            se.insert(z[i].b);
            ans = min(ans,tmp);
        }
        cout<<ans<<endl;
        se.clear();
        cry.clear();
    }
    return 0;
}

闲话:赛场上队友一发O(n^2)居然过了,赛后hack掉了他的AC代码。。。。这里补一下nlogn的做法和学习一下multiset。六级成绩公布了,二战又没过诶,准备一下三战吧,队友6级都过了,室友六级都过了,很多朋友也过了,怎么说呢,有点难受吧,加油吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值