Codeforces Round 909 (Div. 3)

发布时间 2023-12-09 18:13:57作者: 深渊之巅

https://codeforces.com/contest/1899

 

 

一个小游戏

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

int n;

int main() {
    cin >> n;
    
    while(n -- ) {
        int x;
        cin >> x;
        if((x + 1) % 3 == 0 || (x - 1) % 3 == 0) {
            cout << "First" << endl;
        } else {
            cout << "Second" << endl;
        }
    }
    
    
    return 0;
}

 

 

 将数组分成k分,使绝对值差值最大

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>

using namespace std;

const int N = 150010;

typedef long long LL;

int n;
int a[N];
LL s[N];

int main() {
    int T;
    scanf("%d", &T);
    
    while(T -- ) {
        memset(s, 0, sizeof s);
        scanf("%d", &n);
        for(int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);
        for(int i = 1; i <= n; i ++ ) s[i] = s[i - 1] + a[i];
        LL res = 0;
        for(int k = 1; k <= n / 2; k ++ ) {
            if(n % k == 0) {
                LL mi = 1e18, mx = 0;
                for(int j = k; j <= n; j += k) {
                    mi = min(mi, s[j] - s[j - k]);
                    mx = max(mx, s[j] - s[j - k]);
                }
                res = max(res, mx - mi);
            }
        }
        cout << res << endl;
    }
    
    return 0;
}

 

 

 

 找一个和最大的子数组,要求相邻的元素不能有相同的奇偶性

 简单动态规划问题,另f[i]表示以第i项为结尾的,满足条件的最大子序列和。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

const int N = 2e5 + 10;

int n;
int a[N], f[N];

int main() {
    int T;
    scanf("%d", &T);
    
    while(T -- ) {
        scanf("%d", &n);
        for(int i = 0; i < n; i ++ ) scanf("%d", &a[i]), f[i] = a[i];
        for(int i = 1; i < n; i ++ ) {
            if(((a[i] & 1) == (a[i - 1] & 1))) continue;
            f[i] = max(f[i], f[i - 1] + a[i]);
        }
        
        int mx = -1e8;
        for(int i = 0; i < n; i ++ ) mx = max(mx, f[i]);
        printf("%d\n", mx);
    }
    
    
    return 0;
}

 

 

 推公式,按照题目给的条件进行化简即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>

#define LL long long

using namespace std;

const int N = 2e5 + 10;

inline int read(){
    int r = 0,w = 1;
    char c = getchar();
    while (c < '0' || c > '9'){
        if (c == '-') w = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9'){
        r = (r << 3) + (r << 1) + (c ^ 48);
        c = getchar();
    }
    return r * w;
}

int main() {
    
    int n;
    int T = read();
    LL res;
    int x;
    map<int, int> mp;
    map<int,int>::iterator it;
    while(T -- ) {
        res = 0;
        scanf("%d", &n);
        
        mp.clear();
        for(register int i = 0; i < n; ++ i) {
            x = read();
            ++ mp[x];
        }
        
        // 注意这里不能次次声明,会被卡住
        for(it = mp.begin(); it != mp.end(); ++it) {
            res += it -> second * 1ll * (it -> second - 1) / 2;
        }
        
        res += mp[1] * 1ll * mp[2];
        printf("%lld\n", res);
        
    }    
    
    
    return 0;
}

 

 

 贪心,找规律。

我们要得到一个非降序的的序列,操作二可以把小的前移,直到大于等于前一个元素。若我们一直执行操作二,最后会得到一个类似于样例1的序列,然后进行操作一,将大元素插到末尾即可。

在此过程中,如果最小值前面有山峰状数组及形如 3 4 2 的子序列,则无解。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<climits>

using namespace std;

const int N = 2e5 + 10;

int main() {
    int T;
    scanf("%d", &T);
    int a[N];
    int n;
    
    while(T -- ) {
        scanf("%d", &n);
        for(int i = 0; i < n; i ++ ) scanf("%d", &a[i]);    
        int mi = INT_MAX, p = -1;
        for(int i = 0; i < n; i ++ ) {
            if(a[i] < mi) {
                mi = a[i];
                p = i;
            }
        }
        
        bool flag = true;
        for(int i = p; i < n - 1; i ++ ) {
            if(a[i] > a[i + 1]) {
                flag = false;
                break;
            }
        }
        if(flag) printf("%d\n", p);
        else printf("%d\n", -1);
        
    }
    
    
    return 0;
}

 

https://codeforces.com/contest/1899/problem/F

 

 贪心,维护一条链,让链尾部最后一个节点进行移动即可满足题目条件。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

const int N = 510;

int n, q;
int a[N];

int main() {
    int T;
    scanf("%d", &T);
    int len;
    while(T -- ) {
        scanf("%d%d", &n, &q);
        len = n - 1;
        for(int i = 0; i < q; i ++ ) {
            scanf("%d", &a[i]);
        }
        
        for(int i = 1; i < n; i ++ ) {
            printf("%d %d\n", i, i + 1);
        }
        int f = n - 1;
        for(int i = 0; i < q; i ++ ) {
            if(a[i] == f) {
                printf("%d %d %d\n", -1, -1, -1);
            } else {
                printf("%d %d %d\n", n, f, a[i]);
                f = a[i];
            }
        }
        
    }
    
    return 0;
}

 

最后一题太难,贴个链接有空再说:https://codeforces.com/contest/1899/problem/G