【题解】[JOI Open 2021] Monster Game
麻了,并不知道自适应交互器怎么实现的/kk,但是题目还是可以想的(
最开始想直接 std::sort 一遍,事实上这个 \(<\) 没有传递性,会返回各种奇奇怪怪的结果。
事实上这是非常神仙的结论题。
结论:直接归并排序之后的数组满足 \(a_i - a_{i + 1} \le 1\)。
并不知道出题人怎么想到这个神奇的性质,但知道结论后,我们不难直接递归归纳证明。
拥有这个性质的数组并不少见,因为换一种表述,初始数组为 \(0\sim N-1\),然后将原数组分为若干段,每一段取反即可。
所以我们知道前 \(i\) 段的端点,就可以知道第 \(i + 1\) 段的断点。问题转化为找到 \(0\) 的位置。
由于 \(0\) 只会比 \(1\) 小,所以在归并时候,一直在往前跳,感性理解一下。所以排序后 \(0\) 的位置在前 \(\log N\) 个之内。
\(\log N\) 很小,我们直接用 \(N^2\) 算法求出 \(0\) 的位置即可。
/*
Author : SharpnessV
Right Output ! & Accepted !
*/
#include<bits/stdc++.h>
#include"monster.h"
//#define int long long
using namespace std;
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define pre(i, a, b) for(int i = (a);i >= (b);i--)
#define rp(i, a) for(int i = 1; i <= (a); i++)
#define pr(i, a) for(int i = (a); i >= 1; i--)
#define go(i, x) for(auto i : x)
#define pb push_back
std::vector<int> a, b, c;
void msort(int l,int r){
if(l == r)return ;
int mid = (l + r) >> 1, j = l;
msort(l, mid), msort(mid + 1, r);
b.clear();
rep(i, mid + 1, r){
while(j <= mid && !Query(a[j], a[i]))b.pb(a[j ++]);
b.pb(a[i]);
}
while(j <= mid)b.pb(a[j ++]);
rep(i, l, r)a[i] = b[i - l];
}
int cnt[20];
std::vector<int> Solve(int N) {
a.resize(N), b.resize(N), c.resize(N);
rp(i, N)a[i - 1] = c[i - 1] = i - 1;
msort(0, N - 1);
int n = std::min(20, N);
rep(i, 0, n - 1)rep(j, i + 1, n - 1)
if(Query(a[i], a[j]))cnt[i]++;
else cnt[j]++;
int ed = ~0, pre = 0;
rep(i, 0, n - 1)if(!cnt[i])ed = i;
if(-1 == ed){
int p = 0, q = 0;
rep(i, 0, n - 1)if(1 == cnt[i])q = i, std::swap(p, q);
if(Query(a[p], a[q]))ed = p;else ed = q;
}
//cout<< "ss "<<ed << endl;
//rep(i, 0, N - 1)printf("%d ",a[i]);putchar('\n');
reverse(c.begin(), c.begin() + ed + 1);
rep(k, ed + 1, N - 1){
if(Query(a[pre], a[k]))
reverse(c.begin() + ed + 1, c.begin() + k + 1), pre = ed + 1, ed = k;//, cout << "ww " << k <<endl;
}
//rep(i, 0, N - 1)printf("%d ",c[i]);putchar('\n');
rep(i, 0, N - 1)b[a[i]] = c[i];
//rep(i, 0, N - 1)printf("%d ",b[i]);putchar('\n');
return b;
}
/*
g++ monster.cpp grader.cpp -o cur -std=c++14
*/