• 2019 Multi-University Training Contest 1


    不知道错在哪里。
    是要把atop改成stop!两个弄混了。感谢自造样例。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    int n, k;
    char s[100005];
    int cnt[100005][26];
    
    deque<int> pos[26];
    
    int l[26];
    int r[26];
    int used[26];
    
    char ans[100005], atop;
    
    bool check1(int id) {
        //能不能放够下界
        //id表示剩余序列的起始位置
        int restlen = k - atop;
        int sumli = 0;
        for(int i = 0; i < 26; ++i) {
            if(cnt[id][i] < l[i] - used[i])
                return false;
            sumli += l[i] - used[i];
        }
        if(sumli > restlen)
            return false;
        //上界加起来够不够放满?
        int sumri = 0;
        for(int i = 0; i < 26; ++i) {
            sumri += r[i] - used[i];
        }
        if(sumri < restlen)
            return false;
        return true;
    }
    
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        while(~scanf("%s%d", s + 1, &k)) {
            for(int i = 0; i < 26; ++i) {
                pos[i].clear();
                used[i] = 0;
            }
            n = strlen(s + 1);
            for(int i = 1; i <= n; ++i) {
                pos[s[i] - 'a'].push_back(i);
                for(int j = 0; j < 26; ++j) {
                    cnt[i][j] = 0;
                }
                ++cnt[i][s[i] - 'a'];
            }
            for(int i = n - 1; i >= 1; --i) {
                for(int j = 0; j < 26; ++j) {
                    cnt[i][j] += cnt[i + 1][j];
                }
            }
            for(int i = 0; i < 26; ++i) {
                scanf("%d%d", &l[i], &r[i]);
            }
            atop = 0;
            bool suc2 = true;
            while(atop < k) {
                ++atop;
                //给第1个位置选
                bool suc = false;
                for(int i = 0; i < 26; i++) {
                    while(pos[i].size() && pos[i].front() < atop)
                        pos[i].pop_front();
    
                    if(used[i] < r[i] && pos[i].size()) {
                        used[i]++;
                        if(check1(pos[i].front() + 1)) {
                            suc = true;
                            ans[atop] = 'a' + i;
                            ans[atop + 1] = '';
                            pos[i].pop_front();
                            break;
                        }
                        used[i]--;
                    }
                }
                if(!suc) {
                    suc2 = false;
                    break;
                }
            }
            if(suc2)
                printf("%s
    ", ans + 1);
            else
                puts("-1");
        }
    }
    

    有一个可以导致出错的样例:

    abcdeabcdeabcdeabcdeabcdeabcde 14
    0 3
    2 3
    3 5
    3 5
    3 7
    0 0
    0 0
    0 0
    0 0
    0 0
    0 0
    0 0
    0 0
    0 0
    0 0
    0 0
    0 0
    0 0
    0 0
    0 0
    0 0
    0 0
    0 0
    0 0
    0 0
    0 0
    

    目前通过的代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    int n, k;
    char s[100005];
    int cnt[100005][26];
    
    deque<int> pos[26];
    
    int l[26], r[26], used[26];
    
    char ans[100005];
    
    int atop, stop;
    
    bool check1(int id) {
        //能不能放够下界
        //id表示剩余序列的起始位置
        int restlen = k - atop;
        int sumli = 0;
        for(int i = 0; i < 26; ++i) {
            if(cnt[id][i] < l[i] - used[i])
                return false;
            sumli += max(l[i] - used[i], 0);
        }
        if(sumli > restlen)
            return false;
        //上界加起来够不够放满?
        int sumri = 0;
        for(int i = 0; i < 26; ++i) {
            sumri += min(r[i] - used[i], cnt[id][i]);
        }
        if(sumri < restlen)
            return false;
        return true;
    }
    
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        while(~scanf("%s%d", s + 1, &k)) {
            memset(used, 0, sizeof(used));
            n = strlen(s + 1);
            for(int i = 0; i < 26; ++i) {
                pos[i].clear();
                used[i] = 0;
                cnt[n + 1][i] = 0;
            }
            for(int i = 1; i <= n; ++i) {
                pos[s[i] - 'a'].push_back(i);
                for(int j = 0; j < 26; ++j) {
                    cnt[i][j] = 0;
                }
                ++cnt[i][s[i] - 'a'];
            }
    
            for(int i = n - 1; i >= 1; --i)
                for(int j = 0; j < 26; ++j)
                    cnt[i][j] += cnt[i + 1][j];
            for(int i = 0; i < 26; ++i)
                scanf("%d%d", &l[i], &r[i]);
    
            atop = 0;
            stop = 0;
            bool suc2 = true;
            while(atop < k) {
                ++atop;
                //给第1个位置选
                bool suc = false;
                for(int i = 0; i < 26; i++) {
                    while(pos[i].size() && pos[i].front() <= stop)
                        pos[i].pop_front();
    
                    if(used[i] < r[i] && pos[i].size()) {
                        used[i]++;
                        if(check1(pos[i].front() + 1)) {
                            suc = true;
                            ans[atop] = 'a' + i;
                            ans[atop + 1] = '';
                            stop = pos[i].front();
                            pos[i].pop_front();
                            break;
                        }
                        used[i]--;
                    }
                }
                if(!suc) {
                    suc2 = false;
                    break;
                }
            }
            ans[k + 1] = '';
            if(suc2)
                printf("%s
    ", ans + 1);
            else
                puts("-1");
        }
    }
    
  • 相关阅读:
    docker入门(一)
    netstat命令
    grep的小技巧
    gd库的安装
    jar命令的用法详解
    关于awk的范围模式功能问题
    更换文本中第二次出现的字符串内容
    awk打印第n个参数到最后一个技巧/将n行组成一列
    awk -f program.file 功能使用
    shell的变量处理
  • 原文地址:https://www.cnblogs.com/Yinku/p/11231505.html
Copyright © 2020-2023  润新知