CF1408F Two Different

CF1408F Two Different

挺好的一道思维题。

手玩几个例子之后发现以下性质:

1、直接变的话,只能同时把 \(2^k\) 个数变成一样的,次数大概是 \(2^{k - 1} \times k\)

2、零散的小堆可以向大堆借数。(初始值就是纯纯的干扰条件。。。)

3、考虑把性质 \(2\) 推广到极致:对于任意一个 \(n \in [2^k, 2^{k + 1})\),只需要先对前 \(2^k\) 处理一遍,再对后 \(2^k\) 处理一遍即可。具体的处理方法的话,找找下标规律就可以了(分治也可以)。估算一下操作次数不超过 \(2 \times (2 ^ {13} \times 13) = 212,992\)

时间复杂度 \(O(2n \log n)​\)

#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l); i <= (r); ++ i)
#define G(i,r,l) for(int i(r); i >= (l); -- i)
using namespace std;
using ll = long long;
const int N = 3e4;
const int Q = 6e5;
int n, q;
int ans[Q][2];
void insert(int x, int y){
	++ q;
	ans[q][0] = x;
	ans[q][1] = y; 
}
signed main(){
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	cin >> n;
	int m = __lg(n) / __lg(2), r = 1 << m;
	F(i, 0, m - 1){
		int t = 1 << (i + 1);
		for(int j = 1; j <= r; j += t){
			F(k, j, j + t / 2 - 1){
				insert(k, k + t / 2);
			}
		}
	}
	int delta = n - r;
	if(delta == 0){
		cout << q << '\n';
		F(i, 1, q) cout << ans[i][0] << ' ' << ans[i][1] << '\n';
	}
	else{
		cout << q * 2 << '\n';
		F(i, 1, q) cout << ans[i][0] << ' ' << ans[i][1] << '\n';
		F(i, 1, q) cout << ans[i][0] + delta << ' ' << ans[i][1] + delta << '\n';
	}
	return fflush(0), 0;
}
posted @ 2025-10-04 18:15  superl61  阅读(10)  评论(0)    收藏  举报