CodeForces-1185D Extra Element
题目链接:CodeForces-1185D Extra Element
题意
给出长度为$n$的序列,删除一个元素使得剩下的元素可以排列成等差数列,如果可以,输出删除元素的序号,如果不能,输出-1。
思路
由于只能删除一个元素,所产生的等差数列并不会有很多种可能,所以可以从公差入手,不必每个元素都去尝试删除。
$n==2$时必定有解,删除第一个元素即可。
$n>2$时可能的公差只有三种情况:
- 序列中第二小的数$-$最小的数;
- 序列中第三小的数$-$第二小的数;
- 序列中第三小的数$-$最小的数。
对于每种可能的公差遍历排序后的序列,统计要删除多少个数才能满足这个公差即可,删除的数量$<=1$表示有解。
边界情况可能要注意一下,如何处理看个人技巧和习惯。
代码实现
#include <cstdio> #include <cstring> #include <algorithm> #include <utility> using std::pair; using std::sort; const int N = 200010; pair<int, int> arr[N]; // first: 数组元素的值,second: 下标 // 计算数组[s,n)范围内要删除多少个才能满足公差为d,并把删除的数的原下标赋值给ans int check(int d, int s, int n, int &ans) { int res = 0, pre = arr[s].first; for (int i = s + 1; i < n; i++) { if (arr[i].first - pre != d) ans = arr[i].second, res++; else pre = arr[i].first; if (res > 1) return res; } return res; } bool print(int tmp, int ans) { if (tmp == 1) return printf("%d\n", ans); else if (tmp == 0) return printf("%d\n", arr[0].second); return false; } int main() { int n; while (~scanf("%d", &n)) { for (int i = 0; i < n; i++) { scanf("%d", &arr[i].first); arr[i].second = i + 1; } if (n == 2) { puts("1"); continue; } sort(arr, arr + n); int ans, tmp; // 公差为第二小的数减最小的数 tmp = check(arr[1].first - arr[0].first, 0, n, ans); if (print(tmp, ans)) continue; // 公差为第三小的数减第二小的数 tmp = check(arr[2].first - arr[1].first, 1, n, ans); if (tmp == 0) { printf("%d\n", arr[0].second); continue; } // 公差为第三小的数减最小的数 tmp = check(arr[2].first - arr[0].first, 0, n, ans); if (!print(tmp, ans)) puts("-1"); } return 0; }
作者:_kangkang
本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。