Codeforces Round #605 (Div. 3)

Posted waautomaton

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #605 (Div. 3)相关的知识,希望对你有一定的参考价值。

地址:http://codeforces.com/contest/1272

A. Three Friends

仔细读题能够发现|a-b| + |a-c| + |b-c| = |R-L|*2 (其中L = min{a, b, c}, R = max{a, b, c})

那么本题的移动条件就只考虑两个端点L, R即可,答案即为 |(L+1)-(R-1)| 即L向右移动1,R向左移动1,在此之前判断一下原L,R之间的距离是否<=2,<=2输出0

技术图片
#include <bits/stdc++.h>
using namespace std;

int q, a[3];
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    cin >> q;
    while( q-- ){
        for( int i=0; i<3; i++ ) cin >> a[i];
        sort(a, a+3);
        if( a[2]-a[0]<=2 ) cout << "0" << endl;
        else cout << (a[2]-a[0]-2)*2 << endl;
    }

    return 0;
}
A.Three Friends

B.Snow Walking Robot

这题比赛时没做出来??理解题意出了锅。

思路:如果能够回到(0, 0)需满足数量U=D且R=L,只需要上下方向选min(U, D),左右方向选min(L, R)。

如果U=0或D=0那么就要删除所有的另外一个方向,且将左右方向置为1(min(L, R)>0),对于R和L也一样要满足该条件,上下方向置为1(min(U, D)>0)

然后最后组合的时候只需要让路径构成一个环即可,这个组合可以任意组合,做题的时候卡在这了。。。

技术图片
#include <bits/stdc++.h>
using namespace std;

int q, cl, cr, cu, cd;
string s;
int main(){
    // freopen("in.txt", "r", stdin);
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    cin >> q;
    while( q-- ){
        cin >> s;
        cl = cr = cu = cd = 0;
        for( char i:s ){
            cl += i==L;
            cr += i==R;
            cu += i==U;
            cd += i==D;
        }
        cu = min(cu, cd);
        cl = min(cl, cr);
        if( cu==0 || cl==0 ){
            cl = min(1, cl);
            cu = min(1, cu);
        }
        string ans;
        for( int i=0; i<cl; i++ ) ans += R;
        for( int i=0; i<cu; i++ ) ans += U;
        for( int i=0; i<cl; i++ ) ans += L;
        for( int i=0; i<cu; i++ ) ans += D;
        cout << ans.size() << endl << ans << endl;
    }

    return 0;
}
B.Snow Walking Robot

C.Yet Another Broken Keyboard

给k个字母问这k的字母能构成字符串s中多少个子串。

set存一下这k个字母,对s中每一段连续的可以在set中查找到的分别进行统计汇总即可,每一段长度len_i对答案的贡献为(len_i)*(len_i+1)/2.

技术图片
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
int n, k;
string s;
set<char> a;
ll ans, tmp;
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    cin >> n >> k >> s;
    for( int i=0; i<k; i++ ){
        char ch;
        cin >> ch;
        a.insert(ch);
    }
    int len = s.size();
    for( int i=0; i<len; i++ ){
        if( a.find(s[i])!=a.end() )
            tmp ++;
        else{
            ans += tmp*(tmp+1)/2;
            tmp = 0;
        }
    }
    if(tmp) ans += tmp*(tmp+1)/2;
    cout << ans << endl;

    return 0;
}
C.Yet Another Broken Keyboard

D. Remove One Element

三遍预处理 + 一遍原序列

第一遍预处理处理出来一个数不删的最大长度。

第二遍预处理从i from 1~n记录l[i]从左到右递增的最长连续序列长度。

第三遍预处理从i from n~1记录r[i]从右到左递减的最长连续序列长度。

最后跑原序列i from 1~n判断删除i之后的结果能否更新第一遍记录的答案

技术图片
#include <bits/stdc++.h>
using namespace std;

const int maxn = 2e5 + 5;
int a[maxn], n, l[maxn], r[maxn], ans;
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    cin >> n;
    for( int i=0; i<n; i++ ) cin >> a[i];
    int tmp = 1;
    for( int i=1; i<n; i++ ){
        if( a[i]>a[i-1] ) tmp++;
        else tmp = 1;
        ans = max(ans, tmp);
    }
    l[0] = 1;
    for( int i=1; i<n; i++ ){
        if( a[i]>a[i-1] ) l[i] = l[i-1]+1;
        else l[i] = 1;
    }
    r[n-1] = 1;
    for( int i=n-2; ~i; i-- ){
        if( a[i]<a[i+1] ) r[i] = r[i+1]+1;
        else r[i] = 1;
    }
    for( int i=1; i<n-1; i++ )
        if( a[i-1]<a[i+1] ) ans = max(ans, l[i-1]+r[i+1]);
    cout << ans << endl;

    return 0;
}
D. Remove One Element

E.Nearest Opposite Parity

比赛时dfs写MLE,时间不够放弃。

预处理 + bfs通过,使用bfs理由->最短路

预处理出来答案为1的点,然后放进队列,同时将所有点i from 1~n可以跳到的位置i-a[i]和i+a[i]连边然后bfs

技术图片
#include <bits/stdc++.h>
using namespace std;

const int maxn = 2e5 + 5;
const int inf = 0x3f3f3f3f;
int n, a[maxn], ans[maxn];
vector<int> p[maxn];
int main(){
    memset( ans, -1, sizeof(ans) );
    scanf("%d", &n);
    for( int i=0; i<n; i++ ) scanf("%d", &a[i]);
    queue<int> q;
    for( int i=0; i<n; i++ ){
        if( i-a[i]>=0 ){
            p[i-a[i]].push_back(i);
            if( a[i-a[i]]%2 != a[i]%2 ) ans[i] = 1;
        }
        if( i+a[i]<n ){
            p[i+a[i]].push_back(i);
            if( a[i+a[i]]%2 != a[i]%2 ) ans[i] = 1;
        }
        if( ans[i]==1 ) q.push(i);
    }
    while( q.size() ){
        int x = q.front();
        q.pop();
        for( auto i:p[x] ){
            if( ans[i]==-1 && a[i]%2==a[x]%2 ){
                ans[i] = ans[x]+1;
                q.push(i);
            }
        }
    }
    for( int i=0; i<n; i++ ){
        printf("%d", ans[i]);
        if( i==n-1 ) puts("");
        else putchar( );
    }

    return 0;
}
E.Nearest Opposite Parity

以上是关于Codeforces Round #605 (Div. 3)的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #605 (Div. 3) ABCDE 题解

Codeforces Round #605(Div3)A~E

Codeforces Round #605 (Div. 3) E. Nearest Opposite Parity

Codeforces Round #605 (Div. 3) E - Nearest Opposite Parity

Codeforces Round #605 (Div. 3) F. Two Bracket Sequences 三维dp

Codeforces Round #605 (Div. 3) E - Nearest Opposite Parity (超级源点)