zoukankan      html  css  js  c++  java
  • Codeforces Round #706 (Div. 2) A-D题解

    写在前边

    链接:Codeforces Round #706 (Div. 2)
    (A,B,C,D),这场有点简单,不过由于A写炸了后边题连看都没看就溜了,就从上大分变成了掉大分

    A. Split it!

    链接:A题链接

    题目大意:

    给定一个字符串(s),和一个数字(k),那么(a_i)(s)的一个子串,(R(a_i))代表(a_i)的逆序,问是否满足:

    [s = a_1 + a_2 + ... + a_k + a_{k + 1} + R(a_k) + R(a_{k - 1}) + ... + R(a_1) ]

    思路

    首先要知道,有一个单独的(a_{k + 1})部分,那么这部分,根本无所谓,但是对于它的两侧必然要是回文的,一开始就拽着回文串不放了,思维定势,以为全串必然要是回文才行,所以写炸了,所以只需要判断(s[1, k])是否等于(s[n - k + 1, n])(下标从1开始)即可,还要注意的是如果这个串的长度为偶数,那么(k)必然不能等于(cfrac{s.size()}{2})

    代码:

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <vector>
    #include <map>
    #include <cstring>
    
    //#pragma GCC optimize(2)
    //#pragma GCC optimize(3,"Ofast","inline")
    
    using namespace std;
    
    #define Inf 0x3f3f3f3f
    #define PII pair<int, int>
    #define P2LL pair<long long, long long>
    #define endl '
    '
    #define pub push_back
    #define pob pop_back
    
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef vector<long long> VLL;
    typedef vector<int> VI;
    
    const int Mod = 10000007;
    
    LL gcd(LL a, LL b) {
        return b ? gcd(b, a % b) : a;
    }
    
    void solve() {
        string s;
        int n, k;
        cin >> n >> k;
        cin >> s;
        if (k == 0) {
            puts("YES");
            return;
        }
    
        //这题并不一定要求中间是回文的
        if (s.size() % 2 == 0 && k == s.size() / 2) {
            puts("NO");
            return;
        }
        bool flag = true;
        for (int i = 0; i < k; i++) {
            if (s[i] != s[s.size() - 1 - i]) {
                flag = false;
                break;
            }
        }
        puts(flag ? "YES" : "NO");
    }
    
    int main()
    {
        //ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
        int t;
        scanf("%d", &t); 
        while (t--) {
            solve();
        }
        return 0;
    }
    

    B. Max and Mex

    链接:B题链接

    题目大意:

    给定一个序列(s),我们可以进行(k)次操作,每次操作是添加一个(lceil cfrac{a + b}{2} ceil),(a = mex(s)), (b = max(s)),(max)就是序列中最大的数字,(mex)表示序列中最小不存在的非负整数,例如在序列(0,1,2,4)中,那么(mex = 3),问(k)次插入后,(S)中不同数字的个数有多少。

    思路

    先找到第一个(mex),如果(mex <= max(S)),可以发现,插入一个(lceil cfrac{a + b}{2} ceil),永远不会出现这个数,因此,mex就永远不会变化,与此同时插入的值也永远不会大于max,所以mex与max不变,那么序列中不同数的个数最多就加1,用一个set维护就好。
    如果(mex == max(S)),即假设序列为(0,1,2,3),那么第一个(mex)就是(4),所以(lceil cfrac{a + b}{2} ceil)算出来就是(mex),就插入一个新值,所以这种情况下,有多少个(k),就插入多少个新值。

    注意:取最大值的时候要看要注意数组并不一定是严格有序的啊!!

    代码:

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <vector>
    #include <map>
    #include <cstring>
    #include <set>
    
    //#pragma GCC optimize(2)
    //#pragma GCC optimize(3,"Ofast","inline")
    
    using namespace std;
    
    #define Inf 0x3f3f3f3f
    #define PII pair<int, int>
    #define P2LL pair<long long, long long>
    #define endl '
    '
    #define pub push_back
    #define pob pop_back
    
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef vector<long long> VLL;
    typedef vector<int> VI;
    
    
    const int Mod = 10000007;
    
    LL gcd(LL a, LL b) {
        return b ? gcd(b, a % b) : a;
    }
    
    const int N = 1e5 + 10;
    int a[N];
    
    //题目没说给有序数组大哥
    void solve() {
        int n, k;
        scanf("%d%d", &n, &k);
        multiset<int> st2; //记录没有的数字 最小的数字
        set<int> st3;
    
        for (int i = 0; i < n; i++) scanf("%d", &a[i]);       
        
        sort(a, a + n);
        for (int i = 0; i < n; i++) {
            st3.insert(a[i]);
            st2.insert(a[i]);  
        }
    
        if (k == 0) {
            cout << st3.size() << endl;
            return;
        }
    
        int m = 0;
        for (auto &it : st2) {
            if (m != it) {
                break;
            }
            m++;
        }
    
        if (m > a[n - 1]) cout << n + k << endl;
        else {
            st3.insert((m + a[n - 1] + 1) / 2);
            cout << st3.size() << endl;
        }
    }
    
    int main()
    {
        //ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
        int t;
        scanf("%d", &t); 
        while (t--) {
            solve();
        }
    
        return 0;
    }
    

    C. Diamond Miner

    链接:C题链接

    题目大意:

    不说了,太简单了。

    思路

    排序,贪心求值就好了

    代码:

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <vector>
    #include <map>
    #include <cstring>
    #include <cmath>
    
    //#pragma GCC optimize(2)
    //#pragma GCC optimize(3,"Ofast","inline")
    
    using namespace std;
    
    #define Inf 0x3f3f3f3f
    #define PII pair<int, int>
    #define P2LL pair<long long, long long>
    #define endl '
    '
    #define pub push_back
    #define pob pop_back
    
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef vector<long long> VLL;
    typedef vector<int> VI;
    
    const int Mod = 10000007;
    
    const int N = 1e5 + 10;
    
    void solve() {
        int n;
        scanf("%d", &n);
        vector<int> a, b;
        for (int i = 0; i < n * 2; i++) {
            int x, y;
            scanf("%d%d", &x, &y);
            if (x == 0) b.push_back(abs(y));
            if (y == 0) a.push_back(abs(x));
        }
        
        sort(a.begin(), a.end());
        sort(b.begin(), b.end());
        
        double res = 0.0;
        for (int i = 0; i < n; i++) {
            res += sqrt((LL) a[i] * a[i] + (LL) b[i] * b[i]); //千万不要忘记long long
        }
        printf("%.15lf
    ", res);
    }
    
    int main()
    {
        //ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
        int t;
        scanf("%d", &t); 
        while (t--) {
            solve();
        }
    
        return 0;
    }
    

    D. Let's Go Hiking

    链接:D题链接

    题目大意:

    给题目大意转化一下就是,小(A)只能走一条单调递减序列,小(B)只能走一条单调递减序列,直到到某个人走的时候这个人无路可走了那么他就输了。题目中为小(A)先选一个起点,然后小B后选一个起点,接下来,小A先做决策,再B做决策,两者选择永远最优,问最后小A。

    思路

    是一道博弈论的题目,两个人都是在单调的路上走,并且对于(B)来说,肯定要想办法让A输,A肯定想找一条最长的路走,所以有下面几种情况:
    如果两个以上的单调段,那么先手必然输,因为:

    1. 如果是全是一个方向的单调段,那么小(A)无论如何都会被小(B)堵截。
    2. 如果对于山峰段,即一个点左右分别为单调递增单调递减,有多个,那么(B)后手总能选到一个地方赢得比赛(画几个例子试试)。
    3. 如果对于山谷段,及一个点左右分别为单调递减单调递增,有多个,那么(B)后手也同样总能选到一个地方赢得比赛(画几个例子试试)。

    如果就只有一个单调段,那么更不用说了,B只需要放在A旁边堵A即可,赢得比赛。

    所以如果想要先手赢,那么必然是只要一个山峰段,同时山峰段还要左右恰好对称才可以,如果不对称那(B)也可以找一个地方拦截(A),或者走的路比更长,如果对称情况下,(A)必然选择连接点,而这时小(B)只能选两端点,这时如果(A)躲避(B)走另一边,那么它无论如何都输,因此他只能跟(B)对着走,而这时如果(maxl % 2 == 0),那么它依然输,所以只有(maxl % 2 != 0)情况下同时是对称的山峰段才赢,其余情况均输。

    代码:

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <vector>
    #include <map>
    #include <cstring>
    
    //#pragma GCC optimize(2)
    //#pragma GCC optimize(3,"Ofast","inline")
    
    using namespace std;
    
    #define Inf 0x3f3f3f3f
    #define PII pair<int, int>
    #define P2LL pair<long long, long long>
    #define endl '
    '
    #define pub push_back
    #define pob pop_back
    
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef vector<long long> VLL;
    typedef vector<int> VI;
    
    const int Mod = 1000000007;
    
    LL gcd(LL a, LL b) {
        return b ? gcd(b, a % b) : a;
    }
    
    const int N = 1E5 + 10;
    int n, p[N];
    int pre[N], suff[N];
    
    void solve() {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) scanf("%d", &p[i]);
    
        for (int i = 1; i <= n; i++) {
            if (p[i] > p[i - 1]) pre[i] = pre[i - 1] + 1;
            else pre[i] = 1;
        }
        for (int i = n; i >= 1; i--) {
            if (p[i] > p[i + 1]) suff[i] = suff[i + 1] + 1;
            else suff[i] = 1;
        }
    
        /* for (int i = 1; i <= n; i++) cout << pre[i] << " ";
        cout << endl;
        for (int i = 1; i <= n; i++) cout << suff[i] << " ";
        cout << endl; */
    
        int maxl = 0;
        for (int i = 1; i <= n; i++) maxl = max({maxl, pre[i], suff[i]});
    
        int cnt1 = 0, cnt2 = 0, idx1 = 0, idx2 = 0;
        for (int i = 1; i <= n; i++) {
            if (pre[i] == maxl) {
                cnt1++;
                idx1 = i;
            }
            if (suff[i] == maxl) {
                cnt2++;
                idx2 = i;
            }
        }
    
        if (cnt1 + cnt2 != 2) {
            puts("0");
            return;
        } else if (cnt1 + cnt2 == 2 && idx1 == idx2) {   
            puts(maxl % 2 == 0 ? "0" : "1");
        } else puts("0");
    }
    
    int main()
    {
        //ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
        solve();
        return 0;
    }
    
  • 相关阅读:
    PAT 1006 Sign In and Sign Out
    PAT 1004. Counting Leaves
    JavaEE开发环境安装
    NoSql数据库探讨
    maven的配置
    VMWARE 下使用 32位 Ubuntu Linux ,不能给它分配超过3.5G 内存?
    XCODE 4.3 WITH NO GCC?
    在苹果虚拟机上跑 ROR —— Ruby on Rails On Vmware OSX 10.7.3
    推荐一首让人疯狂的好歌《Pumped Up Kicks》。好吧,顺便测下博客园可以写点无关技术的帖子吗?
    RUBY元编程学习之”编写你的第一种领域专属语言“
  • 原文地址:https://www.cnblogs.com/ZhengLijie/p/14528906.html
Copyright © 2011-2022 走看看