This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include "xylophone.h"
#include <bits/stdc++.h>
using namespace std;
template<typename T>
void out(T x) { cout << x << endl; exit(0); }
#define watch(x) cout << (#x) << " is " << (x) << endl
void solve(int N);
int query(int s, int t);
void answer(int i, int a);
using ll = long long;
const ll mod = 1e9+7;
const int maxn = 1e6 + 5;
int A[maxn];
int n;
bool used[maxn];
int A1[maxn];
int A2[maxn];
void Set(int i, int a) {
answer(i,a);
used[a]=true;
A[i]=a;
}
void ask1(int i) {
if (A1[i]) return;
A1[i] = query(i,i+1);
}
void ask2(int i) {
assert(i+2<=n);
if (A2[i]) return;
A2[i] = query(i,i+2);
}
bool isUsed(int x) {
if (x<1 || x>n) return true;
return used[x];
}
void solve(int _n) {
n=_n;
int in = -1;
// find in
{
int lo = 1;
int hi = n;
while (hi-lo>1) {
int mid = (lo+hi)/2;
if (query(1,mid)==n-1) {
hi = mid;
} else {
lo = mid;
}
}
in = hi;
}
auto bruteL = [&](int i) {
//watch(i);
assert(i+2<=n);
assert(A[i+1]); assert(A[i+2]);
ask1(i);
ask1(i+1);
ask2(i);
vector<int> op;
op.push_back(A[i+1]-A1[i]);
op.push_back(A[i+1]+A1[i]);
for (int x: op) {
if (x<1 || x>n) continue;
A[i]=x;
bool ok = true;
int gap=max(abs(A[i]-A[i+1]),abs(A[i+1]-A[i+2]));
if (gap > A2[i]) {
ok = false;
}
if (A1[i] < A2[i] && A1[i+1]==A2[i]) {
// we have to be in the middle
// 2 3 1 or 2 1 3
int lo = min(A[i+1],A[i+2]);
int hi = max(A[i+1],A[i+2]);
if (!(lo<A[i] && A[i]<hi)) {
ok = false;
}
} else if (A1[i]==A2[i] && A1[i+1]<A2[i]) {
// 3 1 2 or 1 3 2
if (A[i+1]<A[i+2]) {
if (!(A[i]>max(A[i+1],A[i+2]))) {
ok = false;
}
} else if (A[i+1]>A[i+2]) {
if (!(A[i]<min(A[i+1],A[i+2]))) {
ok = false;
}
} else {
assert(false);
}
} else if (A1[i]<A2[i] && A1[i+1]<A2[i]) {
// 1 2 3 or 3 2 1
if (A[i+1]<A[i+2]) {
if (!(A[i]<A[i+1])) {
ok = false;
}
}
if (A[i+1]>A[i+2]) {
if (!(A[i]>A[i+1])) {
ok = false;
}
}
} else {
assert(false);
}
if (ok) {
Set(i,x);
break;
}
}
};
auto bruteR = [&](int i) {
// i, i+1, (i+2)
//cout<<"bruteR: "<<i<<endl;
ask1(i);
ask2(i);
ask1(i+1);
assert(A[i]);
assert(A[i+1]);
vector<int> op;
op.push_back(A[i+1]-A1[i+1]);
op.push_back(A[i+1]+A1[i+1]);
for (int x: op) {
if (x<1 || x>n) continue;
if (isUsed(x)) continue;
A[i+2] = x;
bool ok = true;
if (A1[i]<A2[i] && A1[i+1]<A2[i]) {
// 1 2 3 or 3 2 1
if (A[i]<A[i+1]) {
if (!(A[i+1]<A[i+2])) {
ok = false;
}
} else if (A[i]>A[i+1]) {
if (!(A[i+1]>A[i+2])) {
ok = false;
}
} else {
assert(false);
}
} else if (A1[i]==A2[i] && A1[i+1]<A2[i]) {
//watch(i);
// 1 3 2 or 3 1 2
int lo = min(A[i],A[i+1]);
int hi = max(A[i],A[i+1]);
if (!(lo<=A[i+2] && A[i+2]<=hi)) { //???
ok = false;
}
} else if (A1[i+1]==A2[i] && A1[i]<A2[i]) {
//watch(i);
// 2 3 1
// 2 1 3
int lo = min(A[i+1],A[i+2]);
int hi = max(A[i+1],A[i+2]);
if (!(lo<=A[i] && A[i]<=hi)) {
ok = false;
}
if (A[i]>A[i+1]) {
if (!(A[i+2]>A[i])) {
ok = false;
}
} else if (A[i]<A[i+1]) {
if (!(A[i+2]<A[i])) {
ok = false;
}
} else {
assert(false);
}
} else {
assert(false);
}
if (ok) {
Set(i+2,x);
break;
}
}
// 1 2 3
// 1 3 2
// 2 1 3
// 2 3 1
// 3 1 2
// 3 2 1
};
Set(in,n);
// go left
for (int i=in-1; i>=1; i--) {
ask1(i);
int dif=A1[i];
if (isUsed(A[i+1]-dif)) {
Set(i, A[i+1]+dif);
} else if (isUsed(A[i+1]+dif)) {
Set(i, A[i+1]-dif);
} else {
assert(i+2<=n);
bruteL(i);
assert(A[i]);
}
}
for (int i=in; i<n-1; i++) {
ask1(i);
int dif=A1[i];
if (isUsed(A[i]-dif)) {
Set(i+1, A[i]+dif);
} else if (isUsed(A[i]+dif)) {
Set(i+1, A[i]-dif);
} else {
assert(i-1>=1);
bruteR(i-1);
assert(A[i+1]);
}
}
for (int i=1; i<=n; i++) {
if (!isUsed(i)) {
Set(n,i);
break;
}
}
}
///////////////////////////////////////////////////////////////////////////
/*
int nn;
vector<int> v = {-1,4,6,5,1,7,3,2,9,8};
int query(int s, int t) {
assert(s<=t);
int mx=0;
for (int i=s; i<=t; i++) {
for (int j=i; j<=t; j++) {
mx=max(mx,abs(v[i]-v[j]));
}
}
return mx;
}
void answer(int i, int a) {
A[i]=a;
}
void print() {
cout<<"v: ";
for (int i=1; i<=nn; i++) {
cout<<v[i]<<" ";
}
cout<<endl;
cout<<"A: ";
for (int i=1; i<=nn; i++) {
cout<<A[i]<<" ";
}
cout<<endl;
}
vector<int> rand_perm(int n, int index=1) {
assert(n>=1);
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
vector<int> a(n);
iota(a.begin(), a.end(), index);
shuffle(a.begin(), a.end(), rng);
return a;
}
vector<int> genV(int n) {
vector<int> v = rand_perm(n, 1);
v.insert(v.begin(), -1);
int i1= -1; int in = -1;
for (int i=1; i<=n; i++) {
if (v[i]==1) i1=i;
if (v[i]==n) in=i;
}
if (i1>in) {
swap(v[i1],v[in]);
}
//v = {-1, 1, 10, 2, 9, 3, 5, 8, 7, 6, 4};
//v = {-1, 2, 1, 5, 7, 8, 3, 10, 9, 6, 4};
//v = {-1, 6, 2, 5, 8, 7, 9, 1, 10, 3, 4 };
// v = {-1,6, 1, 4, 10, 8, 9, 7, 3, 2, 5 };
// v = {-1,2, 9, 1, 3, 10, 5, 6, 4, 7, 8};
return v;
}
int main() {
ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
v = genV(100);
nn = (int)v.size() - 1;
//print();
solve(nn);
print();
for (int i=1; i<=nn; i++) {
assert(A[i]==v[i]);
}
return 0;
}
*/
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |