Ants
https://codeforces.com/gym/103117/problem/J
相遇反向即可当作穿过了,这是白书上的经典题了。那么不同于那个经典题的地方就在于其两端有障碍限制。我们设总长为
x
x
x ,那么我们发现我们可以把
2
x
2x
2x 作为一个周期,我们发现这个周期内左右内壁均会被碰
n
n
n 次,且所有蚂蚁都会回到原地。那么显然我们中途完整的周期我们都可以直接快速计算,剩下的耐久度比较小,于是我们就可以直接模拟这个过程了。我们可以对左壁和有壁分别建立一个到达时间队列,每次取两个队列中更早到达的那个取出来做处理,我们即可以对这个过程进行模拟。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
const ll x = 1e9 + 1;
ll n, A, B, a[N], d[N], ans;
queue<ll> L, R;
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
scanf("%lld%lld%lld", &n, &A, &B);
for (int i = 1; i <= n; ++i) {
scanf("%lld", &a[i]);
}
ll rnd = min(A, B) / n;
A -= rnd * n, B -= rnd * n;
for (int i = 1; i <= n; ++i) {
scanf("%lld", &d[i]);
}
for (int i = 1; i <= n; ++i) {
if (!d[i]) L.push(a[i]);
}
for (int i = n; i >= 1; --i) {
if (d[i]) R.push(x - a[i]);
}
while(!L.empty() || !R.empty()) {
if (R.empty() || (!L.empty() && L.front() < R.front())) {
ans = max(ans, L.front());
if (A) {
R.push(x + L.front());
A--;
}
L.pop();
}
else {
ans = max(ans, R.front());
if (B) {
L.push(x + R.front());
B--;
}
R.pop();
}
}
printf("%lld\n", ans + 2 * x * rnd);
}