Codeforces Round #579 (Div. 3)简要题解

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_42671946/article/details/99693932

div3真简单

A - Circle of Students

分析:模拟一下两个方向是否成立就可以了。

#include "bits/stdc++.h"
 
using namespace std;
 
int main() {
    int q;
    cin >> q;
    while (q--) {
        int n;
        cin>>n;
        vector<int> v;
        v.reserve(n + 1);
        int st = -1;
        for (int i = 1; i <= n; ++i) {
            scanf("%d", &v[i]);
            if (v[i] == 1)st = i;
        }
        int cnt = 1;
        bool ok = 1;
        for (int i = st; cnt <= n && ok; ++i) {
            if (i > n)i = 1;
            if (v[i] == cnt){
                cnt++;
                continue;
            }
            ok = 0;
        }
        if (ok) {
            puts("YES");
            continue;
        }
        cnt = 1;
        ok = 1;
        for (int i = st; cnt <= n && ok; --i) {
            if (i == 0)i = n;
            if (v[i] == cnt){
                cnt++;
                continue;
            }
            ok = 0;
            cnt++;
        }
        if (ok) {
            puts("YES");
            continue;
        }
        puts("NO");
    }
}

B - Equal Rectangles

分析:每个矩形都要面积相等,那么肯定是最长的两根和最短的两根,次长的两根和次短的两根,依次类推,check一下面积是否相等就可以了。

#include "bits/stdc++.h"
 
using namespace std;
int a[1000];
int main() {
    int t;cin>>t;
    while(t--){
        int n;
        cin>>n;
        for (int i = 1; i <= 4*n; ++i) {
            scanf("%d",&a[i]);
        }
        sort(a+1,a+1+4*n);
        bool ok = 1;
        for (int i = 1; i <= 4*n && ok ; i+=2) {
            if(a[i] != a[i+1])ok=0;
        }
        if(!ok){
            puts("NO");
            continue;
        }
        int s = 0;
        ok = 1;
        for (int i = 1,j = 4*n; i <= 2*n && ok; i+=2,j-=2) {
            if(s==0)s=a[i]*a[j];
            else if(s!=a[i]*a[j])ok = 0;
        }
        if(ok)puts("YES");
        else puts("NO");
    }
}

C - Common Divisors

分析:找出gcd然后求一下gcd的因子个数就可以了。

#include "bits/stdc++.h"
 
using namespace std;
long long a[400004];
int main() {
    int n;
    cin>>n;
    long long g = 0;
    for (int i = 1; i <= n; ++i) {
        scanf("%lld",&a[i]);
        if(g == 0)g = a[i];
        else g = __gcd(a[i],g);
    }
    long long ans = 0;
    for (long long i = 1; i*i <= g; ++i) {
        if(g % i == 0){
            if(i*i!=g)ans += 2;
            else ans += 1;
        }
    }
    cout<<ans<<endl;
}

D1 - Remove the Substring (easy version) && D2 - Remove the Substring (hard version)

分析:可以删去的部分肯定是某个子序列中相邻的两个字符之间的部分,并且要求最长。那么直接求一个最靠前的子序列和一个最靠后的子序列,下标分别表示为pre[i]和suf[i],然后枚举一个分割点i,那么肯定存在一个子序列,这个子序列i以前的下标是pre[i],i以后的下标是suf[i+1],遍历求一遍最大值就可以了。

#include "bits/stdc++.h"
 
using namespace std;
string s, t;
int pre[200004],suf[200004];
int main() {
    cin >> s >> t;
    int pos = 0;
    for (int i = 0; i < s.length(); ++i) {
        if (pos < t.length() && s[i] == t[pos]) {
            pre[pos]=i;pos++;
        }
    }
    pos = t.size() - 1;
    for (int i = s.size() - 1; i >= 0; --i) {
        if (pos >=0 && s[i] == t[pos]) {
            suf[pos]=i;
            pos--;
        }
    }
    int ans = 0;
    for (int i = 0; i < t.size() - 1; ++i) {
        ans = max(suf[i+1] - pre[i] - 1,ans);
    }
    ans = max(ans,max((int)s.size() - 1 - pre[t.size()-1],suf[0]));
    cout << ans << endl;
}

E - Boxers

分析:排序之后从大到小遍历一遍,按照+1,不变,-1,这样的优先级判断就可以了。

#include "bits/stdc++.h"
 
using namespace std;
int a[150004];
 
int main() {
    int n ;
    cin>>n;
    for (int i = 0; i < n; ++i) {
        cin>>a[i];
    }
    int ans = 0;
    sort(a,a+n);
    int last = 1e9;
    for (int i = n-1; i >= 0 ; --i) {
        if(a[i] + 1 < last){
            ans ++;
            last = a[i] + 1;
        }
        else if(a[i] < last){
            ans ++;
            last = a[i];
        }
        else if(a[i] - 1 > 0 && a[i] - 1 < last){
            ans ++;
            last = a[i] - 1;
        }
    }
    cout<<ans<<endl;
}

F1 - Complete the Projects (easy version)

分析:首先把任务分为两部分,一部分b>0,另一部分b<0。优先把b>0的做完再做b<0的,判断b>0能否做完很easy。

对于b<0的部分,对于每个任务,做完这个任务之后的等级的范围是[a+b,∞],同时做完一个任务,等级就会减小。也就是说,要让每个任务都做完,我们只需要按照a-b的大小,从大开始做就可以了。

#include "bits/stdc++.h"
 
using namespace std;
int a[104];
int b[104];
 
struct node {
    int a, b;
 
    bool friend operator<(node a, node b) {
        if (a.a == b.a)return a.b > b.b;
        return a.a < b.a;
    }
};
 
bool cmp(node a, node b) {
    return a.a+a.b > b.a+b.b;
}
 
int main() {
    int n, r;
    cin >> n >> r;
    vector<node> v1, v2;
    priority_queue<node> q;
    for (int i = 1; i <= n; ++i) {
        scanf("%d%d", &a[i], &b[i]);
        if (b[i] >= 0) {
            v1.push_back({a[i], b[i]});
        } else v2.push_back({a[i], b[i]});
    }
    sort(v1.begin(), v1.end());
    sort(v2.begin(), v2.end(), cmp);
    int ans = 0;
    bool ok = 1;
    for (int i = 0; i < v1.size() && ok; ++i) {
        if (v1[i].a <= r){
            ans ++;
            r += v1[i].b;
        }
        else ok = 0;
    }
    if(!ok){
        puts("NO");
        return 0;
    }
    for (int i = 0; i < v2.size(); ++i) {
        if(r >= v2[i].a){
            r += v2[i].b;
            ans++;
        }
        else {
            puts("NO");
            return 0;
        }
    }
    if(r < 0)puts("NO");
    else puts("YES");
}

F2 - Complete the Projects (hard version)

分析:同样按照F1一样的处理方法,对b>0的直接判断,b<0的对a+b从小到大排序后再处理。

用DP[i][j]表示选第i个的时候,从等级j开始,的最大值。

由于对a+b从小到大排序,那么在i前面的一定比i后选,所以dp[i][j]=max dp[i-1][j+b]+1。

#include "bits/stdc++.h"
 
using namespace std;
int a[104];
int b[104];
int dp[104][60004];
 
struct node {
    int a, b;
 
    bool friend operator<(node a, node b) {
        if (a.a == b.a)return a.b > b.b;
        return a.a < b.a;
    }
};
 
bool cmp(node a, node b) {
    return a.a +a.b < b.a + b.b;
}
 
int main() {
    int n, r;
    cin >> n >> r;
    vector<node> v1, v2;
    v2.push_back({0, 0});
    for (int i = 1; i <= n; ++i) {
        scanf("%d%d", &a[i], &b[i]);
        if (b[i] >= 0) {
            v1.push_back({a[i], b[i]});
        } else v2.push_back({a[i], b[i]});
    }
    sort(v1.begin(), v1.end());
    sort(v2.begin() + 1, v2.end(),cmp);
    int ans = 0;
    for (int i = 0; i < v1.size(); ++i) {
        if (v1[i].a <= r) {
            ans++;
            r += v1[i].b;
        } else break;
    }
 
    int maxi = 0;
    for (int i = 1; i < v2.size(); ++i) {
        for (int j = 0; j <= r; ++j) {
            dp[i][j] = dp[i - 1][j];
        }
        for (int j = r; j >= v2[i].a && j + v2[i].b >= 0; --j) {
            dp[i][j] = max(dp[i][j], dp[i - 1][j + v2[i].b] + 1);
            maxi = max(maxi, dp[i][j]);
        }
    }
    cout << ans + maxi << endl;
}

猜你喜欢

转载自blog.csdn.net/qq_42671946/article/details/99693932