Educational Codeforces Round 22

A. The Contest

想一想就知道,提交的时间无所谓,所以我们选择全部做完后的第一个时间间隔提交即可

#include <bits/stdc++.h>

using namespace std;

#define int long long

int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

int32_t main(){
    int n = read() , res = INT_MAX , cnt = 0;
    for( int x ; n ; n -- )
        x = read() , cnt += x;
    int m = read();
    for( int l , r ; m ; m -- ){
        l = read() , r = read();
        if( r < cnt ) continue;
        res = max( l , cnt );
        break;
    }
    if( res == INT_MAX ) res = -1;
    cout << res << "\n";
    return 0;
}

B. The Golden Age

根据乘法原理就可以知道,unlucky 的数字其实不多,最多应该是\(\log_{2}10^{18}\times\log_3 10^{18}\)。我们枚举出所有的数字然后计算下区间大小取最大值即可。

#include <bits/stdc++.h>

using namespace std;

#define int __int128

int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

int32_t main(){
    int x , y , l , r;
    x = read() , y = read() , l = read() , r = read();
    set<int> unlucky;
    for( int a = 1 ; a <= r ; a *= x )
        for( int b = 1 ; a + b <= r ; b *= y )
            unlucky.insert( a + b );
    int res = 0 , last = l;
    for( auto i : unlucky ){
        if( i < l ) continue;
        if( i > r ) break;
        res = max( res , i - last );
        last = i + 1 ;
    }
    res = max( res , r - last + 1 );
    cout << (long long)res << "\n";

    return 0;
}

C. The Tag Game

Bob 的策略其实就是尽可能的远离 Alice ,这样的话,Bob 的选择其实只有三种

  1. 向父节点走
  2. 向子树中最深的方向走
  3. 待在原地

不过要保证的是 Bob在向父节点走的过程中不能和 Alice相遇,这样的话,实际上就是让 Bob沿着1到x的路径最多走到一半,然后在向最深的叶子节点走。这样的话代价就是根到最深的叶子点的距离的二倍。

#include <bits/stdc++.h>

using namespace std;

int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

vector<vector<int>> e;
vector<int> dep , maxdep , fa;

void dfs( int x ){
    maxdep[x] = dep[x];
    for( auto y : e[x] ){
        if( y == fa[x] ) continue;
        fa[y] = x , dep[y] = dep[x] + 1;
        dfs(y);
        maxdep[x] = max( maxdep[x] , maxdep[y] );
    }
    return;
}

int main() {
    int n = read() , s = read();
    e = vector<vector<int>>(n+1);
    dep = vector<int>(n+1);
    fa = vector<int>(n+1);
    maxdep = vector<int>(n+1);
    for( int i = 1 , x , y ; i < n ; i ++ ){
        x = read() , y = read();
        e[x].push_back(y) , e[y].push_back(x);
    }
    fa[1] = -1;
    dfs( 1 );
    int res = maxdep[s] , cnt = 0;
    while(true){
        s = fa[s] , cnt ++;
        if( dep[s] <= cnt ) break;
        res = max( res, maxdep[s] );
    }
    cout << res * 2 << "\n";
    return 0;
}

D. Two Melodies

设状态f[i][j]为一个串选到a[i]一个串选到b[i]的最优解。

很容易就能想到\(O(N^3)\)的转移

    for( int i = 0 ; i <= n ; i ++ )
        for( int j = 0 ; j < i ; j ++ ){
            if( i != 0 ) f[i][j] = max( f[i][j] , f[0][j] + 1 );
            if( j != 0 ) f[i][j] = max( f[i][j] , f[i][0] + 1 );
            for( int k = 1 ; k < i ; k ++ )
                if( abs( a[i] - a[k] ) == 1 || a[i] % 7 == a[k] % 7 )
                    f[i][j] = max( f[i][j] , f[k][j] + 1 );
            for( int k = 1 ; k < j ; k ++ )
                if( abs( a[j] - a[k] ) == 1 || a[j] % 7 == a[k] % 7 )
                    f[i][j] = max( f[i][j] , f[i][k] + 1);
            res = max( res , f[i][j] );
        }

其实我们注意到k的求解是可以优化的,我们用两个桶来维护所有可能的a[k]值的最优解。

#include <bits/stdc++.h>

using namespace std;

int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

int main(){
    int n = read() , res = 0;
    vector<int> a(n+1);
    for( int i = 1 ; i <= n ; i ++ ) a[i] = read();
    vector<vector<int>> f( n+1 , vector<int>(n+1 , LLONG_MAX) );
    for( int i = 0 ; i <= n ; i ++ ){
        vector<int> pre( 100000+1) , mod(7);
        for( int j = 1 ; j < i ; j ++ )
            pre[ a[j] ] = max( pre[ a[j] ] , f[i][j] ),
            mod[ a[j] % 7 ] = max( mod[a[j] % 7] , f[i][j] );
        for( int j = i + 1 ; j <= n ; j ++ ){
            f[i][j] = max( pre[a[j]-1] , pre[a[j]+1] ) + 1;
            f[i][j] = max( f[i][j] , mod[a[j]%7] + 1 );
            f[i][j] = max( f[i][j] , f[i][0] + 1 );
            f[j][i] = f[i][j];
            pre[ a[j] ] = max( pre[ a[j] ] , f[i][j] );
            mod[ a[j] % 7 ] = max( mod[ a[j] % 7 ] , f[i][j] );
            res = max( res , f[i][j] );
        }
    }
    cout << res << "\n";
    return 0;
}
posted @ 2023-07-10 15:40  PHarr  阅读(7)  评论(0编辑  收藏  举报