目录
一. 城市距离
二. 史莱姆
一. 城市距离
(1)思路
每次询问,对于每一个点都判断与下一个点是否为临近点会超时,因此预处理,预先判断每一个点的临近点,然后将花费存入前缀和数组,这样在每次询问直接调用前缀和数组即可。
(2)代码
#include<bits/stdc++.h>
#define LL long long
using namespace std;
LL n, t, x, y, ans, a[100005], s1[100005], s2[100005];
int main()
{
cin >> n;
for (int i = 1; i <= n; i ++)
cin >> a[i];
s1[1] = 0, s1[2] = 1;
for (int i = 3; i <= n; i ++) // 向右走
{
if (a[i] - a[i - 1] < a[i - 1] - a[i - 2])
s1[i] = s1[i - 1] + 1;
else
s1[i] = s1[i - 1] + a[i] - a[i - 1];
}
s2[n] = 0, s2[n - 1] = 1;
for (int i = n - 2; i >= 1; i --) // 向左走
{
if (a[i + 1] - a[i] < a[i + 2] - a[i + 1])
s2[i] = s2[i + 1] + 1;
else
s2[i] = s2[i + 1] + a[i + 1] - a[i];
}
cin >> t;
while (t --)
{
ans = 0;
cin >> x >> y;
if (x < y)
ans = s1[y] - s1[x];
else
ans = s2[y] - s2[x];
printf("%lld /n" ,ans);
}
return 0;
}
二. 史莱姆
(1)思路
对于当前史莱姆,分成其左右两部分。对于左边,并不关心到底是左边哪只史莱姆把它吃掉的,只要从当前史莱姆向左遍历直到覆盖区间内史莱姆质量和大于当前史莱姆质量,只要这个区间内的史莱姆不是质量全部都相等(只要有一个大于其他所有或小于其他所有),就一定会产生一个大史莱姆可以吃掉当前史莱姆。
判断是否出现不同的史莱姆,设一个p来判断即可。
(2)代码
#include<bits/stdc++.h>
#define LL long long
using namespace std;
LL n, ans, ans1, ans2, a[300005], s[300005];
int main()
{
cin >> n;
for (int i = 1; i <= n; i ++)
{
cin >> a[i];
s[i] = s[i - 1] + a[i];
}
for (int i = 1; i <= n; i ++)
{
ans = -1, ans2 = 0;
if (a[i] < a[i - 1] || a[i] < a[i + 1])
{
cout << "1" << endl;
continue;
}
int p = 0;
if (i > 2 && a[i] >= a[i - 1]) // 向左遍历
{
for (int j = i - 2; j >= 1; j --)
{
if (a[j] != a[i - 1]) // 出现第一个不同的史莱姆后,从它开始就能产生大史莱姆
p = 1;
if (p == 1 && s[i - 1] - s[j - 1] > a[i]) // p == 1才会去考虑区间和
{
ans = i - j;
break;
}
}
}
p = 0;
if (i < n - 1 && a[i] >= a[i + 1]) // 向右遍历
{
for (int j = i + 2; j <= n; j ++)
{
if (a[j] != a[i + 1])
p = 1;
if (p == 1 && s[j] - s[i] > a[i])
{
ans2 = j - i;
break;
}
}
}
if (ans != -1 && ans2 != 0)
ans = min(ans, ans2);
if (ans == -1 && ans2 != 0)
ans = ans2;
cout << ans << endl;
}
return 0;
}