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级都过了,室友六级都过了,很多朋友也过了,怎么说呢,有点难受吧,加油吧。