CodeForces-1185D Extra Element

题目链接:CodeForces-1185D Extra Element

题意

给出长度为$n$的序列,删除一个元素使得剩下的元素可以排列成等差数列,如果可以,输出删除元素的序号,如果不能,输出-1。


思路

由于只能删除一个元素,所产生的等差数列并不会有很多种可能,所以可以从公差入手,不必每个元素都去尝试删除。

$n==2$时必定有解,删除第一个元素即可。

$n>2$时可能的公差只有三种情况:

  1. 序列中第二小的数$-$最小的数;
  2. 序列中第三小的数$-$第二小的数;
  3. 序列中第三小的数$-$最小的数。

对于每种可能的公差遍历排序后的序列,统计要删除多少个数才能满足这个公差即可,删除的数量$<=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;
}
View Code

 

转载于:https://www.cnblogs.com/kangkang-/p/11345322.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值