B题
- 一共有五项运动,一个运动员比另一个运动员强的标志是至少有三项运动的排名比他小,问谁最强,或者没有
- 不能直接暴力,假设第一个是第一,往后寻找,遇到矛盾就更新新的第一,直到最后,因为只有一个最强的运动员,需要再进行一次验证,如果再发现矛盾就说明不存在最强的运动员
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <cstdio>
#include <map>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 100;
int main(){
ios::sync_with_stdio(false);
int t, n;
cin >> t;
while(t--){
cin >> n;
vector<vector<int>> a(n, vector<int>(5));
for(int i=0;i<n;i++){
for(int j=0;j<5;j++){
cin >> a[i][j];
}
}
int id = 0;
for(int i=1;i<n;i++){
int m = 0;
for(int j=0;j<5;j++){
m += (a[i][j] < a[id][j]);
}
if(m >= 3){
id = i;
}
}
for(int i=0;i<n;i++){
int m = 0;
for(int j=0;j<5;j++){
m += (a[i][j] < a[id][j]);
}
if(m >= 3){
id = -2;
break;
}
}
cout << id + 1 << '\n';
}
return 0;
}
D题
给出了一个数组,问能否构造一个新的数组使得原来的数组的任意一项都能由新数组的某两项作差得到
- 用 4 , 5 , − 1 , 10 4,5,-1,10 4,5,−1,10举例子,因为这里面有 4 − ( − 1 ) = 5 4-(-1)=5 4−(−1)=5,所以能够构造一个数组满足条件,因为如果 a 1 − a 2 = a 3 a_1-a_2=a_3 a1−a2=a3,那么 b 1 − b 2 − ( b 1 − b 3 ) = b 3 − b 2 b_1-b_2 -(b_1-b_3)=b_3-b_2 b1−b2−(b1−b3)=b3−b2,感觉只要a数组里面有某两个子集内部元素之和相等即满足条件
- 换句话说,如果 a 1 = b 1 − b 2 , a 2 = b 2 − b 3 a_1=b_1-b_2,a_2=b_2-b_3 a1=b1−b2,a2=b2−b3,假设还有一个元素 a 3 a_3 a3,如果想满足条件,那么要么有 a 3 = a 1 ∣ ∣ a 3 = a 2 a_3=a_1||a_3=a_2 a3=a1∣∣a3=a2,要么 a 3 = b 1 − b 3 = a 1 + a 2 ∣ ∣ a 3 = b 3 − b 1 = − ( a 1 + a 2 ) a_3=b_1-b_3=a_1+a_2||a_3=b_3-b_1=-(a_1+a_2) a3=b1−b3=a1+a2∣∣a3=b3−b1=−(a1+a2),都是有某两个集合中元素之和相等
- 因为 n n n的范围很小,可以考虑类似状压DP的思路,遍历每一个状态,也就是说一共有 3 n − 1 3^n-1 3n−1个状态,用来判断选哪些数字,以及数字属于哪个集合,这里和二进制的区别就在于二进制有两种情况也就是0和1,而现在有三种情况:如果是数字1则在第一个集合;如果是2则在第二个集合,如果是0则不选这个数字,这样寻找下去,如果能找到一对这样的集合,那么就说明满足条件
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <cstdio>
#include <map>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 100;
int Data[MAXN];
int main(){
ios::sync_with_stdio(false);
int n, t;
cin >> t;
while(t--){
cin >> n;
for(int i=0;i<n;i++) cin >> Data[i];
int p = 1;
bool found = false;
for(int i=0;i<n;i++) p *= 3;
for(int s=1;s<p;s++){
int tmp = s;
int sum = 0;
for(int i=0;i<n;i++){
int m = tmp % 3;
if(m == 1) sum += Data[i];
if(m == 2) sum -= Data[i];
tmp /= 3;
}
if(sum == 0){
found = true;
break;
}
}
cout << (found ? "YES" : "NO") << '\n';
}
return 0;
}