这个题首先要理解恰好有 ti 个芦笋比第i个芦笋的高度更高的含义,其实就是如果将最终状态降序排列,那么第i
个芦笋在排列后的位置序号应该是ti+1,这样才能恰好有 ti 个芦笋比第i个芦笋的高度更高
如果ti为0,意思是有0个芦笋比第i
个芦笋更高,因此i
在降序排列后的序列中排第一个,同样如果ti为1,那这时的i
在序列中排第二个。题目里面说ti是一个0到N
的排列,也就是说生长到最终状态时,对于所有按顺序的ti=x=[0,N],每个对应的i
的长度是递减的,这样就有了一个不等式关系,从初始状态开始算,设最终生长了n
天,就是:
hti1=x时对应的i+nati1=x时对应的i>hti2=x+1时对应的i+nati2=x+1时对应的i
于是我们从0
到N
开始遍历t
的值,找到满足所有不等式的最小的n
天即可
这里我们把ti=x时对应的i用一个数组r
记录,上面说如果ti为0,意思是有0个芦笋比第i
个芦笋更高,也就是说i
的排名其实就是x + 1
,因此我们直接令r[x + 1] = i
。r[y]
就代表排名第y
的是哪个芦笋
有了上面的r
数组,我们把不等式重写为
hri+nari>hri+1+nari+1
移项后分情况讨论有:
{ari+1−ari>0⟹n<hri−hri+1,ari+1−ari<0⟹n>hri−hri+1,ari+1−ari=0⟹{hri−hri+1>0恒成立,hri−hri+1<0∅.
于是我们从头到尾枚举不等式,找到天数n
即可,也就是对所有不等式的解取交集
由于结果是整数,我们要对除法进行处理,上边界为n≤hri−hri+1上取整后-1,下边界为n≥hri−hri+1下取整后+1
c++中默认除法取整是向零取整,并非下取整,因此要用数学库里面的地板除
floor
函数
#include <iostream>
#include <cmath>
using namespace std;
const int N = 2e5 + 10;
int h[N], a[N], r[N], t;
int n;
int T;
int main()
{
cin >> T;
while (T--)
{
cin >> n;
for (int i = 1; i <= n; i++)
cin >> h[i];
for (int i = 1; i <= n; i++)
cin >> a[i];
// 构造r数组
for (int i = 1; i <= n; i++)
{
cin >> t;
// ti个芦笋比第i个大,对应的i的排名就是ti + 1
r[t + 1] = i;
}
// 确定不等式上下边界,最终的答案就是最小的下边界left
int left = 0, right = 1e9 + 10;
for (int i = 1; i < n; i++)
{
if (right == -1)
break;
int A = h[r[i]] - h[r[i + 1]];
int B = a[r[i + 1]] - a[r[i]];
if (B > 0)
right = min(right, (int)ceil(A * 1.0 / B) - 1);
else if (B < 0)
left = max(left, (int)floor(A * 1.0 / B) + 1);
// 无解的情况直接特判出来
else
right = A > 0 ? right : -1;
}
if (left > right)
left = -1;
cout << left << '\n';
}
return 0;
}