题目
题目描述
街上有n棵树,标号为1…n,第i棵树的高度为ai。
定义这n棵树是漂亮的,当且仅当
1. 对于所有的i,ai=an-i+1;
2. 对于1 <= i < n / 2 (不是整除),ai + 1= ai + 1;
比如说 “2 3 4 5 5 4 3 2”和“1 2 3 2 1”是漂亮的而“1 3 3 1”和“1 2 3 1”不是。
现在请问最少修改几棵树的高度(可以变大也可以变小),使得这些树是漂亮的。
输入描述:
第一行一个整数n表示树的数量( 1 <= n <= 100,000)。
第二行n个整数表示树的高度( 1 <= ai <= 100,000)。
输出描述:
输出一个整数表示最少修改树的高度的数目。
示例1
输入
3
2 2 2
输出
1
示例2
输入
4
1 2 2 1
输出
0
【思路】
考虑三个序列:
- 输入的序列a
- 通过调整a最少次得到正确的序列b
- 任意一个正确的辅助序列c
从a变成b不是很好想,不妨先找一个辅助序列c,把a i 和c i 做差,差值相同的a i 一定都属于某一个正确序列,那么把a i 按差值分类,就相当于把含有这些a i 的正确序列按差值分类。只需要找到含有a i 最多正确序列就行了,答案就是n减去它含有的a i 个数。
代码
#include <stdio.h>
int n;
int arr[100005];
int f[100005];
//开一个下标可以为负数的数组
int data[200010] = { 0 };
int* cnt= data+100005;
int main() {
scanf("%d", &n);
int temp;
int ans = 0;
for (int i = 0; i < n; ++i)
scanf("%d", &arr[i]);
//生成任意一个正确序列,保存在f中
f[0] = f[n - 1] = 1;
for (int i = 1;i<=n-1-i; ++i)
f[i] = f[n - 1 - i] = 1 + i;
//根据差值来分类并计数
for (int i = 0; i < n; ++i)
cnt[f[i] - arr[i]]++;
//找到含ai最多的数组的数量
ans = n;
for (int i = -100000; i <= 100000; ++i) {
if (ans > n - cnt[i])ans = n - cnt[i];
}
printf("%d",ans);
}