题目链接
考察知识点
:
二分
,
抽象提取分类讨论
考察知识点: 二分 , 抽象提取分类讨论
考察知识点:二分,抽象提取分类讨论
先考察交换ax,ay或者交换bx,by的情况
我们可以发现对于我们选定要交换的两对数,交换ax,ay和bx,by减小的值是一样的,所以为了方便讨论,我们都以交换bx,by为例
ax ay
bx by
ax < bx && ay < by 我们叫做 正序
ax < bx && ay > by 我们叫做 反序
//正序相交 ax ay bx by 交换bx,by: ax ay by bx 无变化,不考虑
//正序包络 ax ay by bx 交换bx,by: ax ay bx by 无变化,不考虑
//正序不交 ax bx ay by 交换bx,by: ax by ay bx 变大,不考虑
//反序相交 ax by bx ay 交换bx,by: ax bx by ay 变小2*|bx-by| -> 反序相交变成反序不交 //维护lower_bound(l) 然后判断是否小于等于r res=min(res,2*|bx-by|)
//反序包络 ax by ay bx 交换bx,by: ax bx ay by 变小2*|by-ay| -> 反序包络变成正序不交 //维护反序lmin if l >= lmin res = max(res, len*2)
//反序不交 ax bx by ay 交换bx,by: ax by bx ay 变大,不考虑
这里因为需要区分正序反序,所以我们需要每对数的大小关系,所以我们用type表示这一对数的类型,即l<r,就是1反之为0,这样我们就清楚了每一对数的大小情况,然后我们必须在遍历1类型的数对时,用0类型中的数对来凑反序包络,或者反序相交来更新答案
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
LL n;
struct node{
LL l, r;
int type;
node(LL _l,LL _r)
{
type = _l < _r;
l = min(_l, _r);
r = max(_l, _r);
}
bool operator < (const node & tem) const
{
return r > tem.r;
};
};
int main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n;
vector<LL> a(n+10), b(n+10);
for(int i = 1; i <= n; i ++)
{
cin >> a[i];
}
for(int i = 1; i <= n; i ++)
{
cin >> b[i];
}
vector<node> q;
LL sum = 0;
for(int i = 1; i <= n; i ++)
{
sum += abs(a[i] - b[i]);
q.emplace_back(a[i], b[i]);
}
sort(q.begin(), q.end());
LL overlap = 0;
multiset<int> S, T;//T : type=1 S : type = 0
for(int i = 0; i <= n-1; i ++ )
{
int type = q[i].type;
LL l = q[i].l;
LL r = q[i].r;
if(type == 0)
{
if(T.size())
{
if(l >= (*T.begin()))
{
overlap = max(overlap, 2*(r-l));
}
auto it = T.lower_bound(l);
if(it != T.end() && (*it) <= r)
{
overlap = max(overlap, 2*(r-(*it)));
}
}
S.insert(l);
}
else if(type == 1)
{
if(S.size())
{
if(l >= (*S.begin()))
{
overlap = max(overlap, 2*(r-l));
}
auto it = S.lower_bound(l);
if(it != S.end() && (*it) <= r)
{
cout << "1 " << 2*(r-(*it)) << endl;
overlap = max(overlap, 2*(r-(*it)));
}
}
T.insert(l);
}
}
cout << (sum-overlap) << endl;
return 0;
}