SMU Summer 2023 Contest Round 7

发布时间 2023-07-28 20:08:52作者: Ke_scholar

SMU Summer 2023 Contest Round 7

A. Two Rival Students

  • 答案不能大于 \(n-1\)

  • 如果竞争对手之间的当前距离小于 \(n - 1\) ,我们总是可以将这个距离增加一个交换数;

即答案等于 \(min(n - 1,|a - b|+x)\)

#include <bits/stdc++.h>
#define int long long

using namespace std;

signed main() {

    ios::sync_with_stdio(false);cin.tie(nullptr);

    int T;
    cin >> T;
    while(T--){
        int n,x,a,b;
        cin >> n >> x >> a >> b;
        cout << min(abs(a - b) + x, n - 1) << endl;
    }
    
    return 0;
}

B. Magic Stick

\(1\)不能转化为任何其他数 \(2\)可以转化为\(3\)\(1\),而\(3\)只能转化为\(2\)。也就是说,如果是\(x = 1\),那么只有\(y = 1\)可以达到;如果是\(x = 2\)\(x = 3\),那么\(y\)应该小于\(4\)

否则,我们可以把 \(x\)设得越大越好,所以如果 \(x > 3\),那么任何 \(y\)都是可以达到的。

#include <bits/stdc++.h>
#define int long long

using namespace std;

signed main() {

    int T;
    cin >> T;
    while(T--){
        int x,y;
        cin >> x >> y;

        if (x > 3) puts("YES");
        else if (x == 1) puts(y == 1 ? "YES" : "NO");
        else puts(y <= 3 ? "YES" : "NO");
    }

    return 0;
}

C. Dominated Subarray

  • \(n<2\)和所有数都只出现一次的时候,是不存在这种连续的子序列的
  • 要满足最短连续子序列,只要让一个数最多出现两次就好了,一个\(pos\)数组去记录每个数上次出现的下标,然后当它再次出现时,就用当前坐标减去上次出现的坐标就是一个序列的长度了,每次去更新最小值即可
#include <bits/stdc++.h>
#define int long long

using namespace std;

signed main() {

    ios::sync_with_stdio(false);cin.tie(nullptr);

    int T;
    cin >> T;
    while(T--){
        int n;
        cin >> n;
        int ma = 0;
        vector<int> a(n),t(n + 1),pos(n + 1, -1);
        for(auto& i : a) {
            cin >> i;
            t[i] ++;
            ma = max(ma, t[i]);
        }

        if(n < 2 || ma == 1){
            cout << -1 << endl;
            continue ;
        }

        int mi = 0x3f3f3f3f3f3f;
        for(int i = 0;i < n;i++){
            if(pos[a[i]] != -1)
                mi = min(mi, i - pos[a[i]] + 1);
            pos[a[i]] = i;
        }

        cout << mi << endl;
    }

    return 0;
}

D. Yet Another Monster Killing Problem(二分+贪心)

  • 当英雄里最大的力量值也小于怪兽里最大的力量值得话,英雄们就不能全部打败怪兽了

  • 若力量值为\(p_i\)的英雄能杀死怪兽,则比他大的也一定能打败怪兽,所以我们可以先对力量值排序

    若力量值大的耐久值也高,则他完全可以代替力量值耐久值都比不过他的英雄,所以我们可以从大到小将耐久值更新为后面英雄的最大耐久值,即\(S_i < S_j\),则把\(S_i\)更新为\(max_{i \leq j \leq m}S_j\).

    然后我们可以去枚举每个怪兽,去维护一个当天能打败的最大怪兽数,即打败怪兽的英雄的最小耐久值\(nows\),直到当天能打败的怪兽数和之前打败的怪兽数之和小于了当前所在怪兽数,就是说怪兽已经超过了当天能打败的最大数,那我们就可以把他们消灭掉,然后进入下一天了.

#include <bits/stdc++.h>
#define int long long

using namespace std;

typedef pair<int,int> PII;

signed main() {

    ios::sync_with_stdio(false);cin.tie(nullptr);

    int T;
    cin >> T;
    while(T--){
        int n,m,MaxMonster = 0, MaxHero = 0;
        cin >> n;
        vector<int> a(n);
        for(auto &i : a) {
            cin >> i;
            MaxMonster = max(MaxMonster , i);
        }
        cin >> m;
        vector<PII> ps(m);
        for(auto &[p,s] : ps){
            cin >> p >> s;
            MaxHero = max(MaxHero, p);
        }

        if(MaxMonster > MaxHero){
            cout << -1 << endl;
            continue ;
        }

        sort(ps.begin(),ps.end());
        for(int i = m - 2;i >= 0;i--)
            ps[i].second = max(ps[i + 1].second, ps[i].second);

        int ans = 1, nowkill = 0,nows = 0x3f3f3f3f3f3f;
        for(int i = 0;i < n;i ++){
            int now = lower_bound(ps.begin(),ps.end(), PII(a[i],0),[](PII value,PII x){
                return x.first > value.first;
            }) - ps.begin();

            nows = min(nows, ps[now].second);
            if(nows + nowkill <= i){
                nows = ps[now].second;
                ans++;
                nowkill = i;
            }

        }
        cout << ans << endl;
    }

    return 0;
}