Codeforces练习题题解(一)

A.Consecutive Points Segment-1671B

题意:

一条横轴上存在若干点,所有的点都不相同且严格递增。规定可以对每个点进行一次左移、右移或不变的操作,目标使所有点连续。

思路:

对于连续的点,当左端点或右端点移动时,所有的点需要跟随它一起移动;当两个点之间存在一个空隙,通过一次左移或右移使它们连续;当两个点之间存在两个空隙,通过左右点分别进行一次移动使它们连续。而整个轴上的空隙数量不会发生改变,也就是说空隙数量必须\leq 2,才能实现。

另解:

要使最终序列连续,则点对应位置不能相差过大,首尾点间最多有两个位置可以不填入点。因此只需要计算首尾差值就可以判断能否达成目标

代码:

解法1:

#include <bits/stdc++.h>
#define int long long
const int maxn = 2e5 + 10;

using namespace std;
int t;
int a[maxn];

signed main() {
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cin >> t;
	while(t--)
	{
		int n; cin >> n;
		int cnt = 0;
		for(int i = 1; i <= n; i++){
			cin >> a[i];
		}
		for(int i = 2; i <= n; i++){
			cnt += a[i] - a[i - 1] - 1;
		}
		cout << (cnt > 2 ? "NO" : "YES") << endl;
	}
	return 0;
}

解法2:

#include <bits/stdc++.h>
#define int long long
const int maxn = 2e5 + 10;

using namespace std;
int t;
int a[maxn];

signed main() {
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cin >> t;
	while(t--)
	{
		int n; cin >> n;
		int cnt = 0;
		for(int i = 1; i <= n; i++){
			cin >> a[i];
		}
		if(a[n] - a[1] <= n + 1){
			cout << "YES" << "\n";
		} else {
			cout << "NO" << "\n"; 
		}
	}
	return 0;
}

思考:

在考虑单个点的操作时,可以将其转化成多个点的共同操作,并且要遵守某个原则(在这道题当中是保持连续性),并且将每次操作所产生的影响,用一个更容易量化的东西来表达(这道题中就是中间空隙的个数)。

 B.Make it Increasing-1667A

题意:

给定长度为n的数组a,现有一个长度为n且初始化为0的数组b。

每次操作可以选择一个下标i,使bi + aibi - ai

求最少多少次操作可以使b严格升序。\left ( n\leq 5000 \right )

思路:

要使b数组严格递增,那么一定使以某个位置pos为轴,左边全做减法,右边全做加法。

n \leq 5000是可以接受O(n^{2})的复杂度的,那么可以确定一个pos位置,分别计算两边需要进行操作的次数k,贪心出最小

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值