昨晚状态不好, 翻车了,今天正序补题吧
题意:给你一个数组
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<bits/stdc++.h>
#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<bits/stdc++.h>
#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<bits/stdc++.h>
#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();
}
题意: 给定长度为 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<bits/stdc++.h>
#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();
}
数论, 不会, 摆烂了
E题有机会再补吧