C. Epidemic in Monstropolis

http://codeforces.com/contest/733/problem/C

一道很恶心的模拟题。

注意到如果能凑成b[1],那么a的前缀和一定是有一个满足是b[1]的,因为,如果跳过了一些前面的数不用,就会剩下一个多余的东西在哪里。所以就是把a数组分成了若干段,判断每一段是否凑成b[i]了,

能凑成b[i]的条件是:

这一段a[]中,最大值的左边或者右边要有一个比它小,然后吃了它,就能吃全部了。

注意当只有1个的时候,是一定是true的。不用吃其他了,

剩下的就是恶心的模拟了,因为它的下标不断变换。

所以我就用了一个vector去存。

删除vector中的元素要用迭代器。

复杂度是O(n)的,

总体复杂度O(n*n)

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 500 + 20;
int a[maxn];
int b[maxn];
int n, k;
vector<int>arr;
struct node {
    int pos;
    char ch;
    node() {}
    node(int a, char b) : pos(a), ch(b) {}
}show[maxn];
int lenshow;
bool slove(int begin, int end, int how) {
    if (begin == end) return true;
    int mx = -inf;
    arr.clear();
    for (int i = 1; i <= how; ++i) arr.push_back(inf);
    for (int i = begin; i <= end; ++i) {
        mx = max(mx, a[i]);
    }
    int pos = inf;
    for (int i = begin; i <= end; ++i) {
        if (a[i] == mx) {
            if (i > begin && mx > a[i - 1]) {
                pos = i - begin + 1;
                break;
            }
            if (i < end && mx > a[i + 1]) {
                pos = i - begin + 1;
                break;
            }
        }
    }
    if (pos == inf) return false;

    for (int i = begin; i <= end; ++i) arr.push_back(a[i]);
    vector<int> :: iterator it = arr.begin() + pos + how - 1;
    vector<int> :: iterator it2;


    int all = end - begin + 1;
    pos = pos + how - 1;
    int tbegin = how;
    int tend = arr.size() - 1;

    while (true) {
        if (pos > tbegin && arr[pos] > arr[pos - 1]) {
            show[++lenshow] = node(pos, 'L');
            arr[pos - 1] += arr[pos];
            it2 = it;
            arr.erase(it2);
            it--;
//            cout << *it << endl;
            pos--;
            all--;
            tend = arr.size() - 1;
            if (all == 1) return true;
        }
        if (pos < tend && arr[pos] > arr[pos + 1]) {
            show[++lenshow] = node(pos, 'R');
            arr[pos + 1] += arr[pos];
            it2 = it;
            arr.erase(it2);
//            cout << *it << endl;
//            it = arr.begin() + how + pos - 1;
            tend = arr.size() - 1;
            all--;
            if (all == 1) return true;
        }
    }
    return true;
}
void work() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
    }
    scanf("%d", &k);
    for (int i = 1; i <= k; ++i) {
        scanf("%d", &b[i]);
    }
    int how = 1;
    int begin = 1;
    int up = 0;
    for (int i = 1; i <= k; ++i) {
        int total = 0;
        bool flag = false;
        int tbegin = begin;
        while (begin <= n) {
            total += a[begin];
            if (total == b[i]) {
                flag = slove(tbegin, begin, how);
                up = begin;
                how++;
                begin++;
                break;
            }
            begin++;
            if (total > b[i]) {
                printf("NO
");
                return;
            }
        }
        if (flag == false) {
            printf("NO
");
            return;
        }
    }
    if (up != n) {
        cout << "NO" << endl;
        return;
    }
    cout << "YES" << endl;
    for (int i = 1; i <= lenshow; ++i) {
        printf("%d %c
", show[i].pos, show[i].ch);
    }
}

int main() {
#ifdef local
    freopen("data.txt","r",stdin);
#endif
    work();
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6022438.html