如下代码不能通过测试点 #19,原因是 Wrong anwser.
// Stop the noise and stop the clocks
// Problem: P9721 [EC Final 2022] Inversion
// Contest: Luogu
#include<bits/stdc++.h>
using namespace std;
const int N = 2007;
int n, f[N][N], vis[N][N], a[N], p[N];
int ask (int l, int r) {
// assert (l <= r);
// assert (l <= n and r <= n and l > 0 and r > 0);
if (vis[l][r]) return f[l][r];
cout << "? " << l << " " << r << endl;
cin >> f[l][r]; vis[l][r] = 1;
cout << endl;
return f[l][r];
}
int query (int x, int y) {
if (x + 1 == y) return ask (x, y);
else return ask (x, y) ^ ask (x + 1, y) ^ ask (x, y - 1) ^ ask (x + 1, y - 1);
}
int main () {
cin >> n;
for (int i = 1; i <= n; i ++) a[i] = i, vis[i][i] = 1;
for (int i = 2; i <= n; i ++) {
int l = 1, r = i - 1, pos = i;
while (l <= r) {
int mid = (l + r) >> 1;
if (query (a[mid], a[i])) pos = mid, r = mid - 1;
else l = mid + 1;
}
for (int j = i; j > pos; j --) a[j] = a[j - 1];
a[pos] = i;
assert (pos > 0 and pos <= i);
for (int j = 1; j <= i; j ++) p[a[j]] = j;
if (i == n) for (int j = 1; j <= n; j ++) assert (p[a[j]] == j);
for (int j = i - 1, res = 0; j; j --) {
res ^= (p[j] > p[i]);
f[j][i] = f[j][i - 1] ^ res;
vis[j][i] = 1;
}
if (i == n) for (int j = 1; j <= n; j ++) assert (p[a[j]] == j);
if (i == n) {
cout << "! ";
for (int j = 1; j <= n; j ++) p[a[j]] = j;
for (int j = 1; j <= n; j ++) cout << p[j] << " ";
break;
exit (0);
}
}
// for (int j = 1; j <= n; j ++) assert (p[a[j]] == j);
cout << endl;
}
而如下代码可以通过。
#include<bits/stdc++.h>
using namespace std;
const int N = 2007;
int n, f[N][N], vis[N][N], a[N], p[N];
int ask (int l, int r) {
// assert (l <= r);
// assert (l <= n and r <= n and l > 0 and r > 0);
if (vis[l][r]) return f[l][r];
cout << "? " << l << " " << r << endl;
cin >> f[l][r]; vis[l][r] = 1;
return f[l][r];
}
int query (int x, int y) {
if (x + 1 == y) return ask (x, y);
else return ask (x, y) ^ ask (x + 1, y) ^ ask (x, y - 1) ^ ask (x + 1, y - 1);
}
int main () {
cin >> n;
for (int i = 1; i <= n; i ++) a[i] = i, vis[i][i] = 1;
for (int i = 2; i <= n; i ++) {
int l = 1, r = i - 1, pos = i;
while (l <= r) {
int mid = (l + r) >> 1;
if (query (a[mid], a[i])) pos = mid, r = mid - 1;
else l = mid + 1;
}
for (int j = i; j > pos; j --) a[j] = a[j - 1];
a[pos] = i;
assert (pos > 0 and pos <= i);
for (int j = 1; j <= i; j ++) p[a[j]] = j;
for (int j = i - 1, res = 0; j; j --) {
res ^= (p[j] > p[i]);
f[j][i] = f[j][i - 1] ^ res;
vis[j][i] = 1;
}
}
for (int j = 1; j <= n; j ++) p[a[j]] = j;
cout << "! ";
for (int i = 1; i <= n; i ++) cout << p[i] << " ";
cout << endl;
}
可是,下面这份代码并不会通过,理由是 Wa:
#include<bits/stdc++.h>
using namespace std;
const int N = 2007;
int n, f[N][N], vis[N][N], a[N], p[N];
int ask (int l, int r) {
// assert (l <= r);
// assert (l <= n and r <= n and l > 0 and r > 0);
if (vis[l][r]) return f[l][r];
cout << "? " << l << " " << r << endl;
cin >> f[l][r]; vis[l][r] = 1;
return f[l][r];
}
int query (int x, int y) {
if (x + 1 == y) return ask (x, y);
else return ask (x, y) ^ ask (x + 1, y) ^ ask (x, y - 1) ^ ask (x + 1, y - 1);
}
int main () {
cin >> n;
for (int i = 1; i <= n; i ++) a[i] = i, vis[i][i] = 1;
for (int i = 2; i <= n; i ++) {
int l = 1, r = i - 1, pos = i;
while (l <= r) {
int mid = (l + r) >> 1;
if (query (a[mid], a[i])) pos = mid, r = mid - 1;
else l = mid + 1;
}
for (int j = i; j > pos; j --) a[j] = a[j - 1];
a[pos] = i;
assert (pos > 0 and pos <= i);
for (int j = 1; j <= i; j ++) p[a[j]] = j;
for (int j = i - 1, res = 0; j; j --) {
res ^= (p[j] > p[i]);
f[j][i] = f[j][i - 1] ^ res;
vis[j][i] = 1;
}
}
cout << "! ";
for (int i = 1; i <= n; i ++) cout << p[i] << " ";
cout << endl;
}
这份代码返回了 RE,原因是最后的 assert:
// Stop the noise and stop the clocks
// Problem: P9721 [EC Final 2022] Inversion
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P9721
// Time: 2023-10-26 11:53:02
// Memory Limit: 1 MB
// Author: Cocoly1990
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
const int N = 2007;
int n, f[N][N], vis[N][N], a[N], p[N];
int ask (int l, int r) {
// assert (l <= r);
// assert (l <= n and r <= n and l > 0 and r > 0);
if (vis[l][r]) return f[l][r];
cout << "? " << l << " " << r << endl;
cin >> f[l][r]; vis[l][r] = 1;
cout << endl;
return f[l][r];
}
int query (int x, int y) {
if (x + 1 == y) return ask (x, y);
else return ask (x, y) ^ ask (x + 1, y) ^ ask (x, y - 1) ^ ask (x + 1, y - 1);
}
int main () {
cin >> n;
for (int i = 1; i <= n; i ++) a[i] = i, vis[i][i] = 1;
for (int i = 2; i <= n; i ++) {
int l = 1, r = i - 1, pos = i;
while (l <= r) {
int mid = (l + r) >> 1;
if (query (a[mid], a[i])) pos = mid, r = mid - 1;
else l = mid + 1;
}
for (int j = i; j > pos; j --) a[j] = a[j - 1];
a[pos] = i;
assert (pos > 0 and pos <= i);
for (int j = 1; j <= i; j ++) p[a[j]] = j;
if (i == n) for (int j = 1; j <= n; j ++) assert (p[a[j]] == j);
for (int j = i - 1, res = 0; j; j --) {
res ^= (p[j] > p[i]);
f[j][i] = f[j][i - 1] ^ res;
vis[j][i] = 1;
}
if (i == n) for (int j = 1; j <= n; j ++) assert (p[a[j]] == j);
}
for (int j = 1; j <= n; j ++) assert (p[a[j]] == j);
cout << "! ";
for (int j = 1; j <= n; j ++) p[a[j]] = j;
for (int j = 1; j <= n; j ++) cout << p[j] << " ";
cout << endl;
}
四份代码仅仅在最后的输出有差别。
非常让人困惑的是,我仅仅是在最后重新更新了一遍排名数组,就可以通过测试点,但我在循环到 n 时对排名数组进行了一次 assert,他通过了这次 assert,并且在此之后没有任何针对排名数组的操作。
真的无比令人困惑。