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");
    }
}
原文地址:https://www.cnblogs.com/Yinku/p/11231505.html