Codeforces-Round-827-Div-4

注意: \color{red}{注意:} 注意: 个人博客传送门

A. Sum

思路:

  • 基础的判断结构

时间复杂度: O ( 1 ) O(1) O(1)

void solve() {
    int a, b, c;
    std::cin >> a >> b >> c;

    std::cout << ((a + b == c || b + c == a || a + c == b) ? "YES\n" : "NO\n");
}

B. Increasing

思路:

  • 直接排序,比较相邻位置是否可能相等即可

时间复杂度: O ( n ) O(n) O(n)

void solve() {
    int n;
    std::cin >> n;

    std::vector<int> a(n);
    for (int i = 0; i < n; i++) {
        std::cin >> a[i];
    }

    std::sort(a.begin(), a.end());

    for (int i = 1; i < n; i++) {
        if (a[i] == a[i - 1]) {
            std::cout << "NO\n";
            return ;
        }
    }
    std::cout << "YES\n";
}

C. Stripes

思路:

  • 由于题目保证了一定存在,那么我们只需要找到一个可能的一整行全部为R或者一整列都是一个字符B,否则直接输出另外一个字符即可

时间复杂度: O ( 64 ) O(64) O(64)

void solve() {
    std::vector<std::string> s(8);
    for (int i = 0; i < 8; i++) {
        std::cin >> s[i];
    }

    for (int i = 0; i < 8; i++) {
        bool ok = true;
        for (auto c : s[i]) {
            if (c != 'R') {
                ok = false;
                break;
            }
        }
        if (ok) {
            std::cout << "R\n";
            return ;
        }
    }
    std::cout << "B\n";
}

D. Coprime

思路:

  • 题目把 a i a_i ai 的范围设置到 ≤ 1 0 3 \le 10^3 103,那么一定是一个 h a s h hash hash 之类的,我们把每个元素的位置存起来,然后暴力枚举互质的二元组即可
  • 需要注意,一个从前向后,一个从后向前,这个可以使得互质二元组的和近可能的大

时间复杂度: O ( 1 0 6 ) O(10^6) O(106)

constexpr int N = 2E5 + 10;

void solve() {
    int n;
    std::cin >> n;

    std::vector<int> a(N);
    for (int i = 1; i <= n; i++) {
        std::cin >> a[i];
    }

    std::vector<int> p(N);
    for (int i = 1; i <= n; i++) {
        p[a[i]] = i;
    }

    int ans = -1;
    for (int i = 1000; i >= 1; i--) {
        if (!p[i]) {
            continue ;
        }
        for (int j = 1; j <= 1000; j++) {
            if (p[j] && std::gcd(i, j) == 1) {
                ans = std::max(ans, p[i] + p[j]);
            }
        }
    }
    std::cout << ans << "\n";
}

E. Scuza

思路:

  • 用一个 m a x i max_i maxi 数组维护截止到第 i i i 个位置的最大数是多少,然后我们询问的时候直接二分查找下标即可,这样就可以得到

时间复杂度: O ( n + q ) O(n + q) O(n+q)

void solve() {
    int n, q;
    std::cin >> n >> q;

    std::vector<i64> s(n + 1), max(n + 1);
    for (int i = 1; i <= n; i++) {
        int x;
        std::cin >> x;
        max[i] = std::max(1LL * x, max[i - 1]);
        s[i] = s[i - 1] + x;
    }

    while (q--) {
        i64 x;
        std::cin >> x;

        std::cout << s[std::upper_bound(max.begin() + 1, max.end(), x) - max.begin() - 1] << " ";
    }
    std::cout << "\n";
}

F. Smaller

思路:

  • 我们要找到是否可能让 s s s 按照字典序排列小于 t t t 的方案,首先字典序的大小怎么判断?
    • 要比较两个字符串谁小,我们要逐位比较,当比较完较短的字符串,仍然判断不出来谁大谁小,那么这时,就比较长度,长度大的较大,反之较小
  • 然后,我们可以直接记录将 s s s 里的每个字符复制 k k k 遍,比较结果串里的首位字符,如果首位字符相等,且其他字符都相等,这时就比较长度即可

时间复杂度: O ( n × l e n ( s i ) ) O(n \times len(s_i)) O(n×len(si))

void solve() {
    int n;
    std::cin >> n;

    char mins = 'a', mint = 'a';
    char maxs = 'a', maxt = 'a';

    i64 A = 1, B = 1;
    for (int i = 0; i < n; i++) {
    	int d, k;
    	std::string s;
    	std::cin >> d >> k >> s;

    	for (auto c : s) {
    		if (d == 1) {
    			mins = std::min(mins, c);
    			maxs = std::max(maxs, c);
    			A += k;
    		} else {
    			mint = std::min(mint, c);
    			maxt = std::max(maxt, c);
    			B += k;
    		}
    	}
    	if (mins < maxt || (mins == maxt && mins == maxs && mint == maxt && A < B)) {
    		std::cout << "YES\n";
    	} else {
    		std::cout << "NO\n";
    	}
    }
}

G. Orray

思路:

  • 1 0 9 10^9 109 以内,也就 30 30 30 位,我们直接把最高位放在最前面,然后排序 30 30 30 次就行,每次更新当前的 s u m o r sum_{or} sumor

时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)

void solve() {
    int n;
    std::cin >> n;

    std::vector<int> a(n);
    for (int i = 0; i < n; i++) {
        std::cin >> a[i];
    }

    i64 p = 0;
    for (int i = 0; i < std::min(n, 30); i++) {
        std::sort(a.begin(), a.begin() + n - i, [&](int i, int j) {
            return (i | p) < (j | p);
        });
        p |= a[n - i - 1];
    }
    for (int i = n - 1; i >= 0; i--) {
        std::cout << a[i] << " \n"[i == 0];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值