这道题真的很坑 首先 我第一反应是二分最大顶点值 对于每一个点 都有正增长与负增长
当代价负增长大于正增长
说明还可以继续向下二分 未到达最优解
若果代价正增长大于负增长 则说明再向下二分还会增加代价 即已超过了最优解的情况 就向上二分
直到最后即时向下一步就会增加代价 就是最优解法
虽然上述nlogn有道理 但只是局限于单个数组 但是坑爹的是此题 有两个数组 (吓得我都垫起了酒精灯)
而上述方法有独立性 两个数组无法 或者是 不好联系起来
于是 神奇的数学方法上线了
对于一个n的序列 设最低点n/2高度为h 则向左向右分别为 h+1,h+2…………h+n/2
要是代价最小 就是是 h[i]最接近于 a[i]
即h+n/2-i+1 -> a[i]
数学优化 h = a[i]-(n/2-i+1)
对于如下的情况
i h j
______。__________。______。_________________
h点 在ij之间是
i点j点h点有最小距离
就是此题的最小价值
以此类推 孩子用将放有h的数组一个sort
然后取中位数
再用每一个h减去中位数 取绝对值
即为ans
对于此题 将两个城堡并在一起
形成 \/\/ 形状
再来上述操作
就可一乐
神奇的数学方法近似优化到了 o(n)
数学大法好orz orz
还有一点。。。。数据的高度在longlong范围内
我用int 溢出 wa了一次 QAQ
说明还可以继续向下二分 未到达最优解
若果代价正增长大于负增长 则说明再向下二分还会增加代价 即已超过了最优解的情况 就向上二分
直到最后即时向下一步就会增加代价 就是最优解法
虽然上述nlogn有道理 但只是局限于单个数组 但是坑爹的是此题 有两个数组 (吓得我都垫起了酒精灯)
而上述方法有独立性 两个数组无法 或者是 不好联系起来
于是 神奇的数学方法上线了
对于一个n的序列 设最低点n/2高度为h 则向左向右分别为 h+1,h+2…………h+n/2
要是代价最小 就是是 h[i]最接近于 a[i]
即h+n/2-i+1 -> a[i]
数学优化 h = a[i]-(n/2-i+1)
对于如下的情况
i h j
______。__________。______。_________________
h点 在ij之间是
i点j点h点有最小距离
就是此题的最小价值
以此类推 孩子用将放有h的数组一个sort
然后取中位数
再用每一个h减去中位数 取绝对值
即为ans
对于此题 将两个城堡并在一起
形成 \/\/ 形状
再来上述操作
就可一乐
神奇的数学方法近似优化到了 o(n)
数学大法好orz orz
还有一点。。。。数据的高度在longlong范围内
我用int 溢出 wa了一次 QAQ
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define LL long long
using namespace std;
int n;
LL s[600000+10];
LL q[600000+10];
LL bz;
LL ans;
void readdata()
{
scanf("%d",&n);
for(int i=1;i<=2*n;i++)
scanf("%d",&s[i]);
}
void solve()
{
for(int i=1;i<=n/2;i++)
q[i]=s[i]-(n/2-i+1);
q[n/2+1]=s[n/2+1];
for(int i=n/2+2;i<=n;i++)
q[i]=s[i]-(i-(n/2+1));
for(int i=n+1;i<=n/2+n;i++)
q[i]=s[i]-(n/2-(i-n)+1);
q[n/2+1+n]=s[n/2+1+n];
for(int i=n/2+2+n;i<=2*n;i++)
q[i]=s[i]-(i-(n/2+1+n));
sort(q+1,q+1+2*n);
bz=q[n];
for(int i=1;i<=2*n;i++)
ans+=(LL)abs(q[i]-bz);
printf("%lld\n",ans);
}
int main()
{
readdata();
solve();
}
本文探讨如何解决双数组问题,通过引入数学优化方法,将复杂问题简化为O(n)时间复杂度的解决方案。详细解释了算法的核心思想,包括二分搜索、数学优化以及数据排序等关键步骤,并通过实例演示了从高复杂度到高效优化的过程。
4万+

被折叠的 条评论
为什么被折叠?



