A.Consecutive Points Segment-1671B
题意:
一条横轴上存在若干点,所有的点都不相同且严格递增。规定可以对每个点进行一次左移、右移或不变的操作,目标使所有点连续。
思路:
对于连续的点,当左端点或右端点移动时,所有的点需要跟随它一起移动;当两个点之间存在一个空隙,通过一次左移或右移使它们连续;当两个点之间存在两个空隙,通过左右点分别进行一次移动使它们连续。而整个轴上的空隙数量不会发生改变,也就是说空隙数量必须,才能实现。
另解:
要使最终序列连续,则点对应位置不能相差过大,首尾点间最多有两个位置可以不填入点。因此只需要计算首尾差值就可以判断能否达成目标
代码:
解法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,使或
。
求最少多少次操作可以使b严格升序。
思路:
要使b数组严格递增,那么一定使以某个位置为轴,左边全做减法,右边全做加法。
是可以接受
的复杂度的,那么可以确定一个pos位置,分别计算两边需要进行操作的次数k,贪心出最小