【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;
}
posted @ 2021-04-03 09:13  Jayun  阅读(58)  评论(0编辑  收藏  举报