Codeforces Round 923 (Div. 3)

D. Find the Different Ones!

Codeforces Round 923 (Div. 3)_第1张图片

分析:如果[l,r]存在两个不相同的数,那么一定存在 ai != aj,且 j = i+1,即这两个数是相邻的。这样的话我们可以用前缀和预处理,然后找pre[j]>pre[l]。

正常从前往后遍历是O(n),我们还有q次查询,时间复杂度O(n2)会超时。因此我们用二分查找来进行查询,时间复杂度O(nlogn)

int a[N], pre[N];//pre[i]表示,从a1->ai相邻不同的对数
void solve() {
	//memset(pre, 0, sizeof pre);
	int n; cin >> n;
	rep(i, 1, n) cin >> a[i];
	rep(i, 2, n) {
		pre[i] = pre[i - 1] + (a[i] != a[i - 1]);
	}
 
	int q; cin >> q;
	while (q--) {
		int l, r; cin >> l >> r;
		//tans;
		//在pre[l,r]里二分找大于pre[l],
		//找到的第一个pre[k]>pre[l],说明有增加的对数,且为a[k-1]和a[k]
		int k = upper_bound(pre + 1 + l, pre + 1 + r, pre[l]) - pre;
		if (k > r) cout << -1 << " " << -1 << endl;
		else cout << k - 1 << " " << k << endl;
 
	}
 
}

E. Klever Permutation

Codeforces Round 923 (Div. 3)_第2张图片

分析:假设一个数组a是k级排列,那么a里有n-k+1组,每组的和与其他组的和的差不大于1。

数组a = {a1,a2,a3,a4,a5,a6,...},

第一,假设k = 3,说明 |(ai+aj+ak) - (aj+ak+al)| <= 1 (ijkl是+1递增的),

等同于 |ai - al| <= 1,我们要控制好ai和al的差小于等于1就行(也就是ai比al大1,或者al比ai大1)。

第二,假设其中一组和为x,那么其他组的和只能为x或者x+1。

第三,只要在奇数位从小到大以k的间隔填入,在偶数位从大到小以k的间隔填入,就可以构造出符合题意的序列。

ps:做完这道题有一点点个人理解,我发现很多题都会在奇数和偶数上下文章。像这题的特点就是“对称性”(我便于自己理解所以这么叫),例如:ai,aj,ak,al的关键是ai和al的放置,有一点“对称”的感觉

int a[N];
void solve() {
	int n, k; cin >> n >> k;
	int f = 1;
	int b = n;
	for (int i = 1; i <= k; i++) {
		if (i % 2) {
			for (int j = i; j <= n; j += k) a[j] = f++;
		}
		else {
			for (int j = i; j <= n; j += k) a[j] = b--;
		}
	}
 
	//tans;
	for (int i = 1; i <= n; i++) {
		cout << a[i] << " ";
	}
	cout << endl;
}

你可能感兴趣的:(c++,算法,开发语言)