zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    SPOJ 10628 求树上的某条路径上第k小的点
    zoj 2112 动态区间求第k大
    SPOJ QTREE 树链剖分
    FZU 2082 过路费
    bzoj 1036 Tree Count
    POJ 3237
    C
    G
    E
    B. Split a Number(字符串加法)
  • 原文地址:https://www.cnblogs.com/WAautomaton/p/12037249.html
Copyright © 2011-2022 走看看