相等序列

题目链接:https://www.nowcoder.com/questionTerminal/7492dceb022a4bbebb990695c107823e

题目描述

题目给定a1,a2...an,这样一个长度为n的序列,现在你可以给其中一些元素加上一个值x(只能加一次),然后可以给另外一些值减上一个值x(只能减一次),剩下的元素不能再进行操作。问最后有没有可能找到一个值x使所有元素的值相等。

输入描述:

输入第一行为一个整数k,代表有k个序列(k<100),接下来有2*k行:
偶数行为一个整数n,代表给定序列的长度(1<=n<=100,000)
奇数行包含n个元素,a1,a2...an,代表序列中的元素(0<=ai<=100,000)
 

输出描述:

输出k行,每行一个YES或者NO
示例1

输入

1
5
1 3 3 2 1

输出

YES

AC代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
    int k;
    cin>>k;
    while(k--)
    {
        int n;
        int x;
        cin>>n;
        set<int> s;
        for(int i=0;i<n;i++)
        {
            cin>>x;
            s.insert(x);
        }
        set<int>::iterator it=s.begin();
        string ans;
        if(s.size()<3) ans="YES";
        else if(s.size()==3)
        {
            if((*s.begin()+*s.rbegin())/2==*(++it)) ans="YES";
            else ans="NO";
        }
        else ans="NO";
        cout<<ans<<endl;
    }
}

 

更加完善的AC_codes:
#include<bits/stdc++.h>
using namespace std;
int main()
{
	int k;
	cin>>k;
	while(k--)
	{
		int n;
		int x;
		cin>>n;
		set<int> s;
		for(int i=0;i<n;i++)
		{
			cin>>x;
			s.insert(x);
		}
		set<int>::iterator it=s.begin();
		string ans;
		if(s.size()<3) ans="YES";
		else if(s.size()==3)
		{
			if((*s.begin()+*s.rbegin())==2*(*(++it))) ans="YES";
			else ans="NO";
		}
		else ans="NO";
		cout<<ans<<endl;
	}
}

  



参考大佬的相关思路:
链接:https://www.nowcoder.com/questionTerminal/7492dceb022a4bbebb990695c107823e
来源:牛客网

序列的某些元素要同时增,减x之后 能够保持所有元素值一样,直接整个遍历计算是不现实的。

我们知道,每次增,减的值应当是固定的,也就是x,那就说明比如:不能拿大的减1,小的加2这种形式,要么大的都减2,小的都加2;要么大的都减1,小的都加1。那要保证某两部分,一部分加x,一部分减x,最后要达到相等,那必然存在一个中介,这个中介是不能动的。就比如1 2 3这个序列,2是不能动的,1,3做减,加操作后,要和2相等,这就是我们所熟知的等差序列性质。那推广一下,1,2和3都可能都多个,比如1 1 1 2 2 2 3 3 3这种,但是唯一不变的就是数的类型只能有3种,不能说1 2 3 4这样子,那就不可能达到相等,因为上面分析过了,只能有1个中介。

思考到这里,就基本可以确定思路了:我们不需要拿出所有的数(1 1 1 2 2 2 3 3 3),而只需要取出一个样本(1 2 3),同时样本数不能超过3个(1 2 3 4是不可以的),然后拿这3个样本来进行等差数列的分析(a[0] + a[2] = 2*a[1]),满足的话ans = “YES”,否则ans = "NO"。当然,不要忘了样本可能只有1个或者2个,那必然ans = "YES"。

而要样本数只拿出一个,当然用的就是set容器了,利用它的去重和排序,我们可以省去大笔功夫,直接进行等差序列判断
链接:https://www.nowcoder.com/questionTerminal/7492dceb022a4bbebb990695c107823e
来源:牛客网

#include <iostream>
#include <set>
#include <string>
using namespace std;
 
int main(){
    int k;  //k个序列
    cin >> k;
    while(k--){
        int n;  //序列长度
        int num; //元素值
        cin >> n;
        set<int> res;  //存储每一行的元素,但是每种类型只能存1个,并且会排序
        for(int i = 0; i < n; ++i){
            cin>>num;
            res.insert(num);
        }
        set<int>::iterator it = res.begin();
        string ans;
        if(res.size() < 3){ 
            ans = "YES";
        }
        else if(res.size() == 3){
            //只能一增一减,又因为是有序的,所以第一个增,第三个减,第二个不变。
            //比如1 5 8 就是不可以的,1 5 9就是可以的,利用等差序列性质
            //注意这里不能用res.end,因为end是指向最后一个元素的下一个位置
            if((*res.begin() + *res.rbegin())/2 == *(++it)){
                ans = "YES";
            }
            else{
                ans = "NO";
            }
        }
        else{
            ans = "NO";
        }
        cout << ans << endl;
    }
    return 0;
}
其他关于等差数列的小trick:
https://www.cnblogs.com/mtcnn/p/9423846.html
https://blog.csdn.net/qq_24489717/article/details/50350449
 
 

 

posted @ 2020-08-02 11:31  龙龙666666  阅读(253)  评论(0编辑  收藏  举报