【題解】[JOI Open 2021] Monster Game
阿新 • • 發佈:2021-08-25
麻了,並不知道自適應互動器怎麼實現的/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 */