이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define int ll
vector<vector<int>> sp1, sp2;
vector<int> lg;
int get1(int l, int r){
int k = lg[r - l + 1];
return max(sp1[l][k], sp1[r - (1 << k) + 1][k]);
}
int get2(int l, int r){
int k = lg[r - l + 1];
return min(sp2[l][k], sp2[r - (1 << k) + 1][k]);
}
signed main(){
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n; cin>>n;
vector<int> x(n + 2);
for (int i = 1; i <= n; i++){
cin>>x[i];
}
x[0] = x[1];
x[n + 1] = x[n];
int q; cin>>q;
vector<int> :: iterator it;
auto left = [&](int k) -> int{
if (k == x[n]) return n;
it = upper_bound(x.begin() + 1, x.end(), k);
return (int) (prev(it) - x.begin());
};
auto right = [&](int k) -> int{
it = lower_bound(x.begin() + 1, x.end(), k);
return (int) (it - x.begin());
};
lg.resize(n + 1);
for (int i = 2; i <= n; i++){
lg[i] = lg[i / 2] + 1;
}
sp1.resize(n + 1);
sp2.resize(n + 1);
for (int i = 1; i <= n; i++){
sp1[i].resize(lg[n] + 1);
sp2[i].resize(lg[n] + 1);
}
for (int i = 1; i <= n; i++){
sp1[i][0] = 2 * x[i] - x[i - 1];
sp2[i][0] = 2 * x[i] - x[i + 1];
}
for (int j = 1; j <= lg[n]; j++){
for (int i = 1; i + (1 << j) <= n + 1; i++){
sp1[i][j] = max(sp1[i][j - 1], sp1[i + (1 << (j - 1))][j - 1]);
sp2[i][j] = min(sp2[i][j - 1], sp2[i + (1 << (j - 1))][j - 1]);
}
}
while (q--){
int s; cin>>s;
ll out = 0;
int i = left(s), j = right(s);
if (i < 2){
cout<<x[n] - s<<"\n";
continue;
}
if (j >= n){
cout<<(s - x[1])<<"\n";
continue;
}
if (s - x[i] <= x[j] - s){
out += (s - x[i]);
s = x[i];
j = i;
}
else {
out += (x[j] - s);
s = x[j];
i = j;
}
while (i > 1 || j < n){
if (i == 1){
out += (x[n] - s);
break;
}
if (j == n){
out += (s - x[1]);
break;
}
int d1 = s - x[i - 1], d2 = x[j + 1] - s;
if (d1 <= d2){
if (get1(2, i) <= x[j + 1]){
out += (s - x[1]);
s = x[1];
i = 1;
continue;
}
// max(k < i): x[k + 1] - x[k] > x[j + 1] - x[k + 1]
// <-> 2 * x[k + 1] - x[k] > x[j + 1]
// <-> sp1[k + 1] > x[j + 1]
// sp1[k + 1][0], ... sp1[i][0]
int l = 1, r = i - 1;
while (l + 1 < r){
int m = (l + r) / 2;
if (get1(m + 1, i) > x[j + 1]){
l = m;
}
else {
r = m - 1;
}
}
if (get1(r + 1, i) > x[j + 1]) l = r;
l++;
out += (s - x[l]);
s = x[l];
if (l >= i) return 1;
i = l;
}
else {
if (get2(j + 1, n - 1) > x[j + 1]){
out += (x[n] - s);
s = x[n];
j = n;
continue;
}
// min(k > j): x[k + 1] - x[k] >= x[k] - x[i - 1]
// <-> 2 * x[k] - x[k + 1] <= x[i - 1]
// <-> sp2[k][0] <= x[i - 1]
// sp2[j + 1][0], ... sp2[k][0]
int l = j + 1, r = n - 1;
while (l + 1 < r){
int m = (l + r) / 2;
if (get2(j + 1, m) <= x[j + 1]){
r = m;
}
else {
l = m + 1;
}
}
if (get2(j + 1, l) <= x[j + 1]) r = l;
out += (x[r] - s);
s = x[r];
if (r <= j) return 1;
j = r;
}
}
cout<<out<<"\n";
}
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |