問題レポートA〜EにCF教育ラウンド78(DIV2)ソリューション

問題レポートA〜EにCF教育ラウンド78(DIV2)ソリューション

A:二つのライバル学生

  • 問題の意味に応じてシミュレートすることができます

  • #include<bits/stdc++.h>
    using namespace std;
    int T;
    int n, x, a, b;
    int main()
    {
        cin >> T;
        while(T--)
        {
            cin >> n >> x >> a >> b;
            if(a > b) swap(a, b);
            while(x != 0)
            {
                if(a > 1) x--, a--;
                else if(a == 1) break;
            }
            while(x != 0)
            {
                if(b < n) x--, b++;
                else if(b == n) break;
            }
            cout << b - a << endl;
        }
        return 0;
    }

B:魔法のスティック

  • 1,2,3行、特に文の減少を拡大して、循環に限り、他のを実行します。

  • #include<bits/stdc++.h>
    using namespace std;
    int main()
    {
        int T;
        cin >> T;
        while(T--)
        {
            int x, y; cin >>x >> y;
            if(x >= y) {
                puts("YES"); continue;
            }
            else
            {
                if(x == 2 && y != 3) {
                    puts("NO");
                    continue;
                }
                if(x == 3 && y != 3)
                {
                    puts("NO");
                    continue;
                }
                if(x == 1 && y != 1)
                {
                    puts("NO");
                    continue;
                }
            }
            puts("YES");
        }
        return 0;
    }

C:支配サブアレイ

  • リニア掃引が再びうまく、実際には、クエリは、同じ距離を2つの要素の最小数であります

  • #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 2e5 + 10;
    int a[maxn], T, n, vis[maxn];
    
    int main()
    {
        scanf("%d", &T);
        while(T--)
        {
            scanf("%d", &n);
            int ans = 0x3f3f3f3f;
            for(int i = 1; i <= n; i++)
            {
                scanf("%d", &a[i]);
                vis[i] = 0;
            }
    
            for(int i = 1; i <= n; i++)
            {
                int x = a[i];
                if(vis[x]) ans = min(i-vis[x], ans);
                vis[x] = i;
            }
    
            if(ans == 0x3f3f3f3f) puts("-1");
            else cout << ans + 1<< endl;
        }
        return 0;
    }

D:もう一つのモンスターキリング問題

  • ハーフ+貪欲

  • 人生の最初の特別な宣告最高の攻撃の英雄とモンスターの最大値は、確かに終了しないことには十分ではありません。

  • 2人の英雄ならば英雄のために、\((i、j)は\ ) と同じ攻撃は、しかし\(> JS \ IS) その後、我々は確かに選択しないでください\(J \)を選択し(私は\)\

  • 我々は続くので(P \)\並べ替え操作は、接尾辞に続いて\(B(I).S \ ) を表す\(I \) \(N- \)最大耐久値。

  • ので、モンスターのために、私たちは、ちょうど彼の攻撃よりも主人公大きいにこのモンスターを見つけることができます\(bは\)向けられてきた(P \)\我々はこの英雄の半分を見つけることができるように、行をソート。

  • 主人公の耐久性は、現在の操作をサポートするのに十分でない場合は、現在のサイクルを殺し、新しい日開き、モンスターのために、ほとんどのモンスターの英雄を殺すことができれば我々は、すべてのモンスターを列挙し、最初の日からスタートすべてのモンスター。

  • #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 2e5 + 10;
    int T, n, m;
    int a[maxn];
    
    struct Node{
        int p, s;
    }b[maxn];
    
    bool cmp(Node a, Node b) {return a.p < b.p;}
    bool cmpp(Node x, int y) {return x.p < y;}
    
    int main()
    {
        cin >> T;
        while(T--)
        {
            int mx = 0;
            scanf("%d", &n);
            for(int i = 1; i <= n; i++) {
                scanf("%d", &a[i]);
                mx = max(mx, a[i]);
            }
            scanf("%d", &m);
            for(int i = 1, x, y; i <= m; i++)
            {
                scanf("%d%d", &x, &y);
                b[i] = {x, y};
            }
            sort(b+1, b+1+m, cmp);
            if(b[m].p < mx)
            {
                puts("-1");
                continue;
            }
    
            for(int i = m - 1; i >= 1; i--)
                b[i].s = max(b[i].s, b[i+1].s);
            int days = 1;
            int las = 0; //上一个怪物
            int cnt = 0x3f3f3f3f; //从上一个怪物杀到现在的英雄的最小耐力
    
            for(int i = 1; i <= n; i++)
            {
                int t = lower_bound(b+1, b+m+1, a[i], cmpp) - b;
                cnt = min(b[t].s, cnt);
                if(cnt + las < i) //当前这只怪物杀不掉了
                {
                    cnt = b[t].s;
                    days += 1;
                    las = i - 1;
                }
            }
            cout << days << endl;
        }
        return 0;
    }

E:コンテスト

  • \(DP \)
  • \は、(F(I、1 / 2/3)\) を表し\(I \)最初の数字\(1,2,3 \)最小手オペランドクラスメートを。
  • 初期状態のための\(X \)\(I \)クラスメートの手がある\(A(X)= I \)
  • ある状態遷移方程式\(F(I、K)=分(F(I、K)、F(I、J)+(K!= A(I + 1)))\) \((1 \当量J \ leq3、J \当量のK \当量3)\)
    • 説明:以来\(1,2,3 \)単調に手で学生のシーケンス番号、そう\(J \のLeq K \)
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
int a[maxn], n;
int f[maxn][5];

int main()
{
    int n1, n2, n3;
    cin >> n1 >> n2 >> n3; n = n1 + n2 + n3;
    for(int i = 1, x; i <= n1; i++) 
        scanf("%d", &x), a[x] = 1;
    for(int i = 1, x; i <= n2; i++)
        scanf("%d", &x), a[x] = 2;
    for(int i = 1, x; i <= n3; i++)
        scanf("%d", &x), a[x] = 3;

    memset(f, 0x3f, sizeof(f));
    f[0][1] = f[0][2] = f[0][3] = 0;

    for(int i = 0; i <= n - 1; i++)
        for(int j = 1; j <= 3; j++)
            for(int k = j; k <= 3; k++)
                f[i+1][k] = min(f[i+1][k], f[i][j] + (k != a[i+1]));

    cout << min(min(f[n][1], f[n][2]), f[n][3]) << endl;

    return 0;
}

F:それら同様の待补ください。

おすすめ

転載: www.cnblogs.com/zxytxdy/p/11879388.html