zoukankan      html  css  js  c++  java
  • codeforce刷题(二)

    CodeForces 1329A Dreamoon Likes Coloring

    题意

    (n)个格子,(m)次操作,第(i)次操作使用第(i)种颜色连续的染(l_i)个格子,求给出任意一种方案,使得:

    • 每个格子都被染上色
    • 每种颜色都要出现,既不能存在一种颜色被完全覆盖

    题解

    显然,如果 (sum_{i = 1}^{m}l_i < n),则不存在这样的方案。
    假如第(i)种颜色就从第(i)个格子开始染色,有两种情况可能出现

    • 如果有 (i + l[i] - 1 > n),则不存在满足条件的方案,因为要染第(i)种颜色,且不超出(n)个格子的方案,只有覆盖掉(i)前面的颜色,所以不满足条件2:不会有颜色被完全覆盖
    • 没有 (i + l[i] - 1 > n),说明(m)次操作没有染完全部的格子或者刚好染完全部的格子。从后向前考虑,第(m)次操作在第 (n - l[m] + 1) 格子处开始染色, 第(m - 1)次操作在第 (n - l[m] - l[m - 1] + 1) 格子处开始染色,第(m - 2)次操作在第 (n - l[m] - l[m - 1] - l[m - 2] + 1) 格子处开始染色,依次递推。在递推的过程中,判断上一种颜色染的区域的末尾是不是超过了当前颜色的染色开始位置。举例来说:如果 ((m - 1) + l[m - 1] >= n - l[m] + 1),说明所有的格子都被染色,且每种颜色都会出现。

    注意是按顺序操作 ,所以不能排序。同时,这也是为什么出现 (i + l[i] - 1 > n) 就代表着(i)前面的颜色会被完全覆盖。非常妙的思想:先紧凑染色,然后从后向前考虑,将染色的区域向后移动,起到补偿的作用。动画演示

    int main()
    {
        cin >> n >> m;
    
        long long sum = 0;
        for (int i = 1; i <= m; ++i) {
            cin >> l[i];
            sum += l[i];
            ans[i] = i;
            
            if (i + l[i] - 1 > n) {
                puts("-1");
                return 0;
            }
        }
    
        if (sum < n) {
            puts("-1");
            return 0;
        }
    
        
        for (int i = m; i >= 1; --i) {
            ans[i] = n - l[i] + 1;
            n = n - l[i];
            if (i - 1 + l[i - 1] >= ans[i]) {
                break;
            }
    
        }
    
        for (int i = 1; i <= m; ++i) cout << ans[i] << " ";
        cout << endl;
        return 0;
    }
    

    CodeForces 1326D2 Prefix-Suffix Palindrome (Hard version)

    给一个字符串(s),求满足如下条件的最长回文串(t)

    • (t = a + b)
    • (a)(s)的前缀((a)可以为空),(b)(s)的后缀((b)可以为空)

    题解

    分类讨论,

    • (t = a),表示(t)(s)前缀且是回文串,马拉车算法求得(p[i])后,判断(i - p[i] == 0),更新答案
    • (t = b),表示(t)(s)后缀且是回文串,判断(i + p[i] == m),更新答案
    • (t = a + b),存在某个(k),使得(s[1] = s[n],s[2] = s[n - 1], ··· , s[k] = s[n - k + 1], s[k + 1] != s[n - k]),掐头(去掉(s[1 - k]))去尾(去掉(s[n - k + 1 - k]))以后,就变成了上述两种情况。用相同的方法解决即可

    换个问题,如果(t)是回文子串,既连续不断,它仍然可以分成两部分,一部分是(s)的前缀,一部分是(s)的后缀。然后求(t)该怎么做?

    void Mana(string s, int n) {
    
        int m = 1;
        vector<char> ma(3 * n);
        vector<int> p(3 * n);
        // inite string s
        ma[0] = '@';
        for (int i = 0; i < n; ++i) {
            ma[m++] = '#';
            ma[m++] = s[i];
        }
        ma[m] = '#';
    
        //printf("%s
    ", ma);
    
        int id = 0, mx = 0, ans = 0, pos = 0;
        for (int i = 0; i < m; ++i) {
            if (i < mx) p[i] = min(mx - i + 1, p[2 * id - i]);
            else p[i] = 1;
            while(ma[i - p[i]] == ma[i + p[i]]) p[i]++;
            if (i + p[i] - 1 > mx) {
                id = i;
                mx = i + p[i] - 1;
            }
            if ((i - p[i] == 0 || i + p[i] == m + 1) && (p[i] - 1 >= ans)) {
                ans = p[i] - 1;
                pos = i;
            }
        }
    
        myfor(i, 0, m) if (pos - p[pos] < i && i < pos + p[pos] && ma[i] != '#') printf("%c", ma[i]);
    }
    
    void solve() {
        string s;
        cin >> s;
    
        int k = 0, n = s.size();
        while(s[k] == s[n - k - 1] && (2 * k + 1 < n)) k++;
    
        if (k > 0) cout << s.substr(0, k);
        if (n > 2 * k) {
            Mana(s.substr(k, n - 2 * k), n - 2 * k);
        }
        if (k > 0) cout << s.substr(n - k, k);
        cout << endl;
    }
    
  • 相关阅读:
    页面后退的总结
    Flash Builder4.6 无法启动,并且报 Failed to create the Java Virtual Machine(1不行的话可以参考下2)
    单独的js代码文件被JSP文件调用,中文乱码问题
    Flash Builder4.6 破解方法的实践
    sql文学习.....关于条件判断的查询....casewhenthen
    解决flash builder 4.6安装过程中安装程序遇到错误(1)
    flex builder 4 控制台不能输出trace()的解决方法
    jstl遍历map,foreach
    jar包直接拷贝到WEBINF/lib下和以userLibrary形式引入的区别?/jar包放置在WEBINF/lib下和通过build path导入的区别是什么?
    flash build 4.6 不能debug 报错 C:\WINDOWS\system32\Macromed\Flash\NPSWF32.dll
  • 原文地址:https://www.cnblogs.com/zgglj-com/p/12659893.html
Copyright © 2011-2022 走看看