HDU-6586 String 2019杭電多校第一場

HDU-6586 String 2019杭電多校第一場

我的博客:https://acmerszq.cn
原題鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=6586

題意

​ 多組輸入,每組第一行輸入一個字符串s和一個數字k,接下來每行輸入26行,每行兩個數字LiL_iRiR_i,代表在長度爲k的子序列中,aza~z在這個範圍中出現。

思路

​ 貪心,記錄每個字母對應的所有位置,每個字母已經放入的數量,每個位置後剩餘的每種字母的數目。當每個字母的使用數量與最大數量相同時跳過,字母的位置沒有到達last位置時,將位置下標一直往後移動。

​ 還需要一個數組用於記錄字母已經用到第幾個。

貪心條件:

1:當前位置的字母已經被選中的加上剩餘的和大於等於最小出現次數LiL_i

2:求已出現次數與最少出現次數的差(小於0時記爲0),並計算出它們的和,和必須小於等於剩下的子序列未放置數量;

3:求i=0nmin()n=25\sum_{i = 0}^n min(字母剩下的數目,最多出現次數-已放置數目)『n = 25』,和必須大於等於可放置數目。

AC代碼

#include <bits/stdc++.h>
using namespace std;
const int SIZE = 1e5+5;
char str[SIZE];
int used[30];
string ansStr;
int hz[SIZE][30];
vector<int> xb[30];
vector<int>::iterator it[30];
struct node {
    int l, r;
} ch[SIZE];
void init() {
    memset(used, 0, sizeof(used));
    memset(hz, 0, sizeof(hz));
    memset(ch, 0, sizeof(ch));
    for(int i = 0; i < 30; i++) {
        xb[i].clear();
    }
    ansStr.clear();
}
int main() {
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
    while(~scanf("%s", str)) {
        init();
        int k = 0;
        scanf("%d", &k);
        int len = strlen(str);
        for(int i = 0; i < 26; i++) {
            scanf("%d%d", &ch[i].l, &ch[i].r);
        }
        for(int i = len-1; i >= 0; i--) {
            for(int j = 0; j < 26; j++) {
                hz[i][j] = hz[i+1][j]+(str[i]=='a'+j);
            }
        }
        for(int i = 0; i < len; i++) {
            xb[str[i]-'a'].push_back(i);
        }
        for(int i = 0; i < 26; i++) {
            it[i] = xb[i].begin();
        }
        bool flag = false;
        int ans = 0;
        int last = -1;
        for(int i = 0; i < k; i++) {
            flag = false;
            for(int j = 0; j < 26; j++) {
                bool ok = true;
                if(used[j] == ch[j].r) continue;
                while((*it[j]) <= last && it[j] != xb[j].end()) it[j]++;
                if(it[j] == xb[j].end()) continue;
                int pos = *it[j];
                int sum = 0;
                used[j]++;
                for(int x = 0; x < 26; x++) {
                    if(used[x]+hz[pos+1][x] < ch[x].l) ok = false;
                    sum += max(0, ch[x].l - used[x]);
                }
                if(sum > k - i - 1) ok = false;
                sum = 0;
                for(int x = 0; x < 26; x++) {
                    sum += min(hz[pos+1][x], ch[x].r - used[x]);
                }
                if(sum < k - i - 1) ok = false;
                if(!ok) {
                    used[j]--;
                } else {
                    flag = true;
                    ansStr.push_back('a' + j);
                    last = pos;
                    break;
                }
            }
            if(!flag) {
                ans = -1;
                break;
            }
        }
        if(ans == -1) printf("-1\n");
        else cout << ansStr << '\n';
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章