Skip to the content.

Codeforces Round #803 (Div. 2) C,D

C. 3SUM Closure

题目描述:给定一个由整数构成的数组,若其中任意三个下标不同的数之和仍在这个数组中,那么称这个数组是 3SUM-closed。求判断一个数组是否是 3SUM-closed 数组,多组测试数据。

思路:若这个数组中有三个及以上正数(或负数),那么我们可以将正数排序,最大的三个正数之和一定不在这个数组中(负数同理)。据此思路对正数个数,负数个数,零个数进行分类讨论即可。

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

int T;
LL a[200010];

void work(){
    int n;
    cin >> n;
    int pos = 0, neg = 0, zro = 0;
    for(int i = 1; i <= n; ++i){
        cin >> a[i];
        if(a[i] > 0)    pos++;
        else if(a[i] < 0)    neg++;
        else if(a[i] == 0)   zro++;
    }
    if(pos >= 3 || neg >= 3){
        cout << "NO" << endl;
        return;
    }
    if(zro){
        if(pos >= 2 || neg >= 2){
            cout << "NO" << endl;
            return; 
        }
        if(pos && neg){
            sort(a + 1, a + 1 + n);
            if(a[1] + a[n] == 0){
                cout << "YES" << endl;
                return;
            }
            cout << "NO" << endl;
            return;
        }
        cout << "YES" << endl;
        return;
    }else{
        if(n == 4){
            LL s1 = a[1] + a[2] + a[3], s2 = a[1] + a[2] + a[4], s3 = a[2] + a[3] + a[4], s4 = a[1] + a[3] + a[4];
            int flg1 = 1, flg2 = 1, flg3 = 1, flg4 = 1;
            for(int i = 1;i <= n; ++i){
                if(a[i] == s1)  flg1 = 0;
                if(a[i] == s2)  flg2 = 0;
                if(a[i] == s3)  flg3 = 0;
                if(a[i] == s4)  flg4 = 0;
            }
            if(flg1 || flg2 || flg3 || flg4){
                cout << "NO" << endl;
                return;
            }
            cout << "YES" << endl;
            return;
        }else{
            LL s = a[1] + a[2] + a[3];
            for(int i = 1; i <= n; ++i){
                if(s == a[i]){
                    cout << "YES" << endl;
                    return;
                }
            }
            cout << "NO" << endl;
            return;
        }
    }
}

int main(){
    cin.tie(0);
    cin >> T;
    while(T--)  work();
    return 0;
}

D. Fixed Point Guessing

题目描述:交互题,一个由 $n$ 个正整数构成的一个排列:$1, 2, \dots, n(3 \leq n \leq 10^4, n\ is\ odd)$,现将其中的 $\frac{n-1}{2}$ 组两两交换,那么肯定会剩余一个数在其本来的位置上没有被交换。现对每个用例可以进行最多 $15$ 次询问,询问一个区间中的数的构成(将从小到大排序后返回给你),输出那个没有被交换的数。

思路:这种交互题一眼二分。二分询问每个区间中的数,如果对 $[l,r]$ 的询问中有奇数个数落在 $[l,r]$ 这个区间中,那么没有被交换的数一定在这个区间中。

注意交互题的缓冲区清空问题。

#include <bits/stdc++.h>
using namespace std;

int T;

int n;

int query(int l, int r){
    cout << "? " << l << " " << r << endl;
    int cnt = 0;
    for(int i = l; i <= r; ++i){
        int x;
        cin >> x;
        if(x >= l && x <= r)    cnt++;
    }
    if(cnt & 1) return 1;
    else        return 0;
}

int work(int l, int r){
    if(l == r)  return l;
    int mid = l + r >> 1;
    if(query(l, mid)){
        return work(l, mid);
    }else{
        return work(mid + 1, r);
    }
}

int main(){
    cin.tie(0);
    cin >> T;
    while(T--){
        cin >> n;
        int ans = work(1, n);
        cout << "! " << ans << endl;
    }
    return 0;
}