昨晚状态不好, 翻车了,今天正序补题吧
A. Good Pairs
题意:给你一个数组 a 1 , a 2 , … , a n a_1,a_2,…,a_n a1,a2,…,an 一个正整数数组。好的一对是一对指数 ( i , j ) (i,j) (i,j) 和 1 ≤ i 、 j ≤ n 1≤i、 j≤n 1≤i、j≤n 因此,对于所有 1 ≤ K ≤ n 1≤K≤n 1≤K≤n、 以下等式成立:
∣ a i − a k ∣ + ∣ a k − a j ∣ ≥ ∣ a i − a j ∣ , |a_i−a_k|+|a_k−a_j|≥|a_i−a_j|, ∣ai−ak∣+∣ak−aj∣≥∣ai−aj∣,
由三角不等式可以只当且仅当 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)≤ak≤max(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 n−1 个操作,使得在应用这些操作之后,列表中唯一剩余的元素等于 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 a1−a2,a3−a2
a 3 − a 2 − a 1 + a 2 a_3 - a_2 - a_1 + a_2 a3−a2−a1+a2
a 3 − a 1 a_3 - a_1 a3−a1
然后不难发现规律, 就是要找任意两项的差为 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题有机会再补吧