Codeforces Global Round 15 B、D两题

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 a1a2=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 b1b2(b1b3)=b3b2,感觉只要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=b1b2,a2=b2b3,假设还有一个元素 a 3 a_3 a3,如果想满足条件,那么要么有 a 3 = a 1 ∣ ∣ a 3 = a 2 a_3=a_1||a_3=a_2 a3=a1a3=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=b1b3=a1+a2a3=b3b1=(a1+a2),都是有某两个集合中元素之和相等
  • 因为 n n n的范围很小,可以考虑类似状压DP的思路,遍历每一个状态,也就是说一共有 3 n − 1 3^n-1 3n1个状态,用来判断选哪些数字,以及数字属于哪个集合,这里和二进制的区别就在于二进制有两种情况也就是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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Clarence Liu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值