CodeTON Round 1 (Div. 1 + Div. 2, Rated, Prizes)

昨晚状态不好, 翻车了,今天正序补题吧

A. Good Pairs

题意:给你一个数组 a 1 , a 2 , … , a n a_1,a_2,…,a_n a1a2an 一个正整数数组。好的一对是一对指数 ( i , j ) (i,j) ij 1 ≤ i 、 j ≤ n 1≤i、 j≤n 1ijn 因此,对于所有 1 ≤ K ≤ n 1≤K≤n 1Kn、 以下等式成立:
∣ a i − a k ∣ + ∣ a k − a j ∣ ≥ ∣ a i − a j ∣ , |a_i−a_k|+|a_k−a_j|≥|a_i−a_j|, aiak+akajaiaj,

由三角不等式可以只当且仅当 m i n ( a i , a j ) ≤ a k ≤ m a x ( a i , a j ) ; min(a_i, a_j) ≤ a_k ≤ max(a_i,a_j); min(ai,aj)akmax(ai,aj);成立, 当然也可以分类讨论证明

#include
#define x first
#define y second
typedef std :: pair<int, int> PII;
#define debug printf("debug\n");
#define gg exit(0);
#define int long long
const int N = 5e5 + 10;

using namespace std;
PII a[N];
void solve()
{
	int n;
	cin >> n;
	int  x;
	for(int i = 1; i <= n; i ++ ) cin >> x, a[i] = {x, i};

	sort(a + 1, a + 1 + n);   //排序

	cout << a[1].second << " " << a[n].second << '\n';  //最大值的下标和最小值的下标
}
signed main()
{
	 int t;
	 cin >> t;
	 while(t -- )
	 	solve();

}

B. Subtract Operation
题意: 你会得到一个 n n n 个整数的数列。可以执行以下操作:从数列中选择一个元素 x x x,从数列中删除 x x x ,然后从所有剩余元素中减去 x x x 的值。因此,在一次操作中,列表的长度正好减少了 1 1 1
给定一个整数 k k k ( k > 0 ) (k>0) k>0,找出是否有 n − 1 n - 1 n1 个操作,使得在应用这些操作之后,列表中唯一剩余的元素等于 k k k

我们可以枚举一种情况
a 1 , a 2 , a 3 a_1, a_2,a_3 a1,a2,a3
a 1 − a 2 , a 3 − a 2 a_1 - a_2, a_3 - a_2 a1a2,a3a2
a 3 − a 2 − a 1 + a 2 a_3 - a_2 - a_1 + a_2 a3a2a1+a2
a 3 − a 1 a_3 - a_1 a3a1

然后不难发现规律, 就是要找任意两项的差为 k k k 的情况,

这里可以用哈希, 也可以用双指针

#include
#define x first
#define y second
typedef std :: pair<int, int> PII;
#define debug printf("debug\n");
#define gg exit(0);
#define int long long
const int N = 5e5 + 10;

using namespace std;
int a[N];
void solve()
{
	int n, k;
	map<int, int>st;
	cin >> n >> k;
	for(int i = 1; i <= n; i ++ ) cin >> a[i], st[a[i]] = 1; //记录是否存在这个数

	for(int i = 1; i <= n; i ++ )
		if(st[a[i] + k])  //如果存在差为k的
		{
			cout << "YES\n";
			return;
		}

	cout << "NO\n";

}
signed main()
{
	 int t;
	 cin >> t;
	 while(t -- )
	 	solve();

}

双指针

#include
#define x first
#define y second
typedef std :: pair<int, int> PII;
#define debug printf("debug\n");
#define gg exit(0);
#define int long long
const int N = 5e5 + 10;

using namespace std;
int a[N];
void solve()
{
	 int n, k;
	 cin >> n >> k;
	 for(int i = 1; i <= n; i ++ ) cin >> a[i];
	 
	 sort(a + 1, a + 1 + n);
	 
	 if(n == 1) cout << (a[1] == k) ? "YES\n" : "NO\n";
	 else 
	 {
	     int i = 1, j = 2;
	     while(j <= n && i <= n )
	     {
	         if(a[j] - a[i] == k)
	         {
	             cout << "YES\n";
	             return;
	         }
	         else if(a[j] - a[i] > k) i ++;
	         else j ++;
	     }
	 }
    cout << "NO\n";
}
signed main()
{
	 int t;
	 cin >> t;
	 while(t -- )
	 	solve();

}

C. Make Equal With Mod

题意: 给定长度为 n n n 的序列 a a a, 每次选择一个大于等于 2 2 2 的数 x x x, 使得整个数列模上 x x x, 然后判断能否使得数列所有元素相等

分析: 首先如果序列中不存在 1 1 1, 是肯定能使得所有元素相等的,
其次 如果既存在 1 1 1 又存在 0 0 0, 因为存在 0 0 0 所以最后只能变成 0 0 0, 但是 1 1 1 又无法变成 0 0 0 (因为只能模 ≥ 2 ≥2 2 的数 ) 所以无解
最后我们如果既 存在 1 1 1, 又不存在 0 0 0, 那我们每次可以模上一个刚好比每一个数小 1 1 1 的数, 比如 5 5 5 变成 1 1 1, 我们可以模 4 4 4, 3 3 3 变成 1 1 1, 模 2 2 2, 但是这里有一种特殊情况, 如果既有 3 3 3 , 又有 4 4 4, 那么我们在模上 2 2 2 之后 4 4 4就变成了 0 0 0, 显然不符合要求, 所以我们必须保证没有连续的数字才合法, 如果存在连续的数字,则无解

#include
#define x first
#define y second
typedef std :: pair<int, int> PII;
#define debug printf("debug\n");
#define gg exit(0);
#define int long long
const int N = 5e5 + 10;

using namespace std;
int a[N];
void solve()
{
	int n;
	cin >> n;
	map<int,int>st;
	for(int i = 1; i <= n; i ++ )
   {
		cin >> a[i];
		st[a[i]] = 1;  //记录状态
    }
   if(!st[1]) //无1
   {
    	cout << "YES\n";
    	return;
   }
   if(st[0])   //有1 有0
   {
 	    cout << "NO\n";
    	return;
   	} 
   	for(int i = 1; i <= n; i ++ )
   		if(st[a[i] + 1])  //连续
   	{
   		//gg
   			cout << "NO\n";
   			return;
   	}
   	  cout << "YES\n";

}
signed main()
{
	 int t;
	 cin >> t;
	 while(t -- )
	 	solve();

}

D. K-good

数论, 不会, 摆烂了

E题有机会再补吧

你可能感兴趣的:(算法,c++)