题解:P17767 「LDOI R2」排列 / Permutation
题解:P17767 「LDOI R2」排列 / Permutation
思路
注意到等价,因此我们不需要还原出数值,可以把
首先我们需要知道每一个点到
对于剩下的点
在掌握了所有点到
先找出距离
之后对于那些距离大于
最后,当每个点的距离
代码
::::success[代码]
#include <bits/stdc++.h>
using namespace std;
int query(int i, int j, int k);
vector<int> tmp, res, rep;
int q, f, s, d, dqr, md;
int dq[100005], b[100005];
int p1[100005], p2[100005], sgn[100005];
bool cmp(int a, int b) { return dq[a] < dq[b]; }
vector<int> solve(int n, int sid)
{
res.clear();
rep.clear();
if (n <= 2)
{
res.push_back(1);
if (n == 2)
res.push_back(2);
return res;
}
int tmp = query(2, 1, 3);
dqr = (query(1, 2, 3) + tmp - query(1, 3, 2)) / 2;
dq[1] = 0;
dq[2] = dqr;
q = 1;
dq[3] = tmp - dqr;
if (dq[3] > dq[q])
q = 3;
for (int i = 4; i <= n; i++)
{
dq[i] = query(2, 1, i) - dqr;
if (dq[i] > dq[q])
q = i;
}
if (dq[2] > dq[q])
q = 2;
d = dq[q], md = s = n - 1 - d;
if (d == s)
md = s - 1;
for (int i = 1; i <= n; i++)
{
int j = dq[i];
if (j >= 1 && j <= s)
{
if (p1[j] == 0)
p1[j] = i;
else
p2[j] = i;
}
}
for (int i = 1; i <= n; i++)
{
if (dq[i] > s)
sgn[i] = -1;
}
if (d == s)
{
sgn[q] = -1;
for (int i = 1; i <= n; i++)
{
if (dq[i] == d && i != q)
{
sgn[i] = 1;
break;
}
}
}
for (int j = 1; j <= md; j++)
{
if (p1[j])
rep.push_back(p1[j]);
}
for (int i = 0; i + 1 < (int)rep.size(); i += 2)
{
int r = rep[i];
int t = rep[i + 1];
int val = query(r, q, t) - 2 * d;
int dr = dq[r], dt = dq[t];
for (int a = -1; a <= 1; a += 2)
{
for (int b = -1; b <= 1; b += 2)
{
if (a * dr + b * dt == val)
{
sgn[r] = a;
sgn[t] = b;
}
}
}
}
if (rep.size() % 2 == 1)
{
int r = rep.back();
int val = query(r, q, 1) - 2 * d;
if (val == dq[r])
sgn[r] = 1;
else
sgn[r] = -1;
}
for (int j = 1; j <= md; j++)
{
int u = p1[j], v = p2[j];
if (u && v)
sgn[v] = -sgn[u];
}
for (int i = 1; i <= n; i++)
b[i] = d + sgn[i] * dq[i] + 1;
for (int i = 1; i <= n; i++)
res.push_back(b[i]);
return res;
}
::::