【CodeForces 1408F】Two Different
链接:
题目大意:
构造 \(q\) 个二元组 \((x_i,y_i)\),每个二元组的操作是把 \(a_{x_i},a_{y_i}\) 的值都变为 \(f(a_{x_i},a_{y_i})\)。\(f(x)\) 意义不重要。顺序对二元组进行操作,你要使得最后 \(a_i\) 最多只有两个不同的数。
\(1\leq n\leq 15000\),\(1\leq q\leq 5\times 10^5\)。
正文:
n 在 2 的整次幂:
按照样例所给的方法,很容易想到一种构造方案(假设 \(n\) 是 \(2\) 的整次幂):
粗略计算一下,如果要把 \(n\) 个数全合并为同一个,方案数有 \(\frac{n\log n}{2}\) 个,可以过。
但是直接算有点麻烦,就可以逆向递归跑。
n 不在 2 的整次幂:
把 \(n\) 分成两个部分 \([1,2^k],[n-2^k+1,n]\) 跑,其中 \(k\) 是最大数且满足 \(2^k<n\)。
代码:
const int N = 135010;
int n, m;
int a[N][2], cnt;
void dfs (int l, int r)
{
if (l == r) return;
int mid = l + r >> 1;
dfs(l, mid), dfs(mid + 1, r);
for (int i = l; i <= mid; i ++)
a[++cnt][0] = i, a[cnt][1] = i - l + mid + 1;
}
int main()
{
scanf ("%d", &n);
for (m = 1; (m << 1) < n; m <<= 1);
dfs(1, m), dfs(n - m + 1, n);
printf ("%d\n", cnt);
for (int i = 1; i <= cnt; i++) printf ("%d %d\n", a[i][0], a[i][1]);
return 0;
}