test 2019-11-01
test 2019-11-01 蒟蒻一枚,弱弱总结——
T1:Dove 下跳棋
问题描述:
Dove 喜爱下跳棋,在传统的跳棋基础之上,Dove 又延伸出了许多别的玩法。Dove 以一个一维数轴为棋盘下跳棋,总共会移动棋子 𝑛 − 1 次。因为讨厌没有规律,所以 Dove 每次只会恰好把棋子向右移动 𝑘 个格子。
Cicada 送给了 Dove 一个长度为 𝑛 的数列 {𝑎},为了表示感谢,Dove 打算以 Cicada
送给他的序列 {𝑎} 为基础下跳棋。具体的,Dove 将会把棋子从编号为 𝑎1 的格子出发,在第
𝑖 次移动后,把棋子移动到编号为 𝑎𝑖+1 的格子。显然 Cicada 送给他的 {𝑎} 有可能不满足
Dove 要求的条件,Dove 想知道,最少需要修改多少个 𝑎𝑖 的值,才能使得这个数列 {𝑎} 是
满足 Dove 需要的移动棋子的要求的。
输入:
第一行输入两个整数 𝑛, 𝑘。接下来一行输入 𝑛 个整数表示 {𝑎},第 𝑖 个数为 𝑎𝑖。
输出:
输出一行一个整数,表示最少需要修改的值的数量。
样例 :
chess1.in
18 -3
78260 -82654 -11527 -83872 -4432 50471 96185 34310 25899 32430 4718 81502 23660 82676 2172 -36826 -64408 -49929
chess1.out
17
约定和数据范围:
对于全部测试点,保证 2 ≤ 𝑛 ≤ 105, |𝑎𝑖|, |k| ≤ 105
| 测试点 | n | k |
| 1,2,3 | ≤ 300 | 0 ≤ k ≤ 3000 |
| 4,5,6 | ≤ 300 | |
| 7,8 | 0 ≤ k | |
| 9,10 |
分析:
算法一:
显然,无论修改多少个位置的数,我们至少需要保留一个位置上的数,全部修改一定不是最优的。如果我们能够确定一个位置 i 是不修改的,那么对于第 j 个位置,我们就能够确定其应该具有的权值应为 ai + (j − i) × k,否则就为要修改的数。
时间复杂度为 O(n2)……
这种算法是可以直接想到的,但时间复杂度太高,有点尴尬,放弃……
算法二:
观察到对于每个位置上的数来说,如果它是不需要修改的。那么他能唯一确定第一个位置上的数。如果我们能够确定一个位置 i 是不修改的,那么对于第 j 个位置,我们就能够确定其应该具有的权值应为 ai + (j − i) × k,根据权值我们再比较一下就得出答案……
时间复杂度为 O(n)……
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 inline long long read() { 5 long long number = 0, symbol = 1; 6 char ch = getchar(); 7 while ('0' > ch || ch > '9') { 8 if (ch == '-') 9 symbol = -1; 10 ch = getchar(); 11 } 12 while ('0' <= ch && ch <= '9') { 13 number = (number << 3) + (number << 1) + (ch ^ 48); 14 ch = getchar(); 15 } 16 return number * symbol; 17 } 18 19 const int maxn = 100000 + 10; 20 long long n, k, a[maxn], cnt, ans; 21 22 int main() { 23 freopen("chess.in", "r", stdin); 24 freopen("chess.out", "w", stdout); 25 n = read(); 26 k = read(); 27 for (int i = 1; i <= n; i++) { 28 a[i] = read(); 29 a[i] = a[i] - ((i - 1) * k); 30 } 31 a[0] = -0x3f3f3f3f; 32 for (int i = 1; i <= n; i++) { 33 if (a[i] != a[i - 1]) 34 cnt = 1; 35 else 36 cnt++; 37 ans = max(ans, cnt); 38 } 39 printf("%lld\n",n - ans); 40 return 0; 41 }

浙公网安备 33010602011771号