제출 #1162670

#제출 시각아이디문제언어결과실행 시간메모리
1162670abysmalGrowing Vegetable is Fun 3 (JOI19_ho_t3)C++20
75 / 100
1098 ms56648 KiB
#include <array>

template <typename T, int NDIMS> struct tensor_view {
    static_assert(NDIMS >= 0, "NDIMS must be nonnegative");

protected:
    std::array<int, NDIMS> shape;
    std::array<int, NDIMS> strides;
    T* data;

    tensor_view(std::array<int, NDIMS> shape_, std::array<int, NDIMS> strides_, T* data_) : shape(shape_), strides(strides_), data(data_) {}

public:
    tensor_view() : shape{0}, strides{0}, data(nullptr) {}

protected:
    int flatten_index(std::array<int, NDIMS> idx) const {
        int res = 0;
        for (int i = 0; i < NDIMS; i++) { res += idx[i] * strides[i]; }
        return res;
    }
    int flatten_index_checked(std::array<int, NDIMS> idx) const {
        int res = 0;
        for (int i = 0; i < NDIMS; i++) {
            assert(0 <= idx[i] && idx[i] < shape[i]);
            res += idx[i] * strides[i];
        }
        return res;
    }

public:
    T& operator[] (std::array<int, NDIMS> idx) const {
#ifdef _GLIBCXX_DEBUG
        return data[flatten_index_checked(idx)];
#else
        return data[flatten_index(idx)];
#endif
    }
    T& at(std::array<int, NDIMS> idx) const {
        return data[flatten_index_checked(idx)];
    }

    template <int D = NDIMS>
    typename std::enable_if<(0 < D), tensor_view<T, NDIMS-1>>::type operator[] (int idx) const {
        std::array<int, NDIMS-1> nshape; std::copy(shape.begin()+1, shape.end(), nshape.begin());
        std::array<int, NDIMS-1> nstrides; std::copy(strides.begin()+1, strides.end(), nstrides.begin());
        T* ndata = data + (strides[0] * idx);
        return tensor_view<T, NDIMS-1>(nshape, nstrides, ndata);
    }
    template <int D = NDIMS>
    typename std::enable_if<(0 < D), tensor_view<T, NDIMS-1>>::type at(int idx) const {
        assert(0 <= idx && idx < shape[0]);
        return operator[](idx);
    }

    template <int D = NDIMS>
    typename std::enable_if<(0 == D), T&>::type operator * () const {
        return *data;
    }

    template <typename U, int D> friend struct tensor_view;
    template <typename U, int D> friend struct tensor;
};

template <typename T, int NDIMS> struct tensor {
    static_assert(NDIMS >= 0, "NDIMS must be nonnegative");

protected:
    std::array<int, NDIMS> shape;
    std::array<int, NDIMS> strides;
    int len;
    T* data;

public:
    tensor() : shape{0}, strides{0}, len(0), data(nullptr) {}

    explicit tensor(std::array<int, NDIMS> shape_, const T& t = T()) {
        shape = shape_;
        len = 1;
        for (int i = NDIMS-1; i >= 0; i--) {
            strides[i] = len;
            len *= shape[i];
        }
        data = new T[len];
        std::fill(data, data + len, t);
    }

    tensor(const tensor& o) : shape(o.shape), strides(o.strides), len(o.len), data(new T[len]) {
        for (int i = 0; i < len; i++) {
            data[i] = o.data[i];
        }
    }

    tensor& operator=(tensor&& o) noexcept {
        using std::swap;
        swap(shape, o.shape);
        swap(strides, o.strides);
        swap(len, o.len);
        swap(data, o.data);
        return *this;
    }
    tensor(tensor&& o) : tensor() {
        *this = std::move(o);
    }
    tensor& operator=(const tensor& o) {
        return *this = tensor(o);
    }
    ~tensor() { delete[] data; }

    using view_t = tensor_view<T, NDIMS>;
    view_t view() {
        return tensor_view<T, NDIMS>(shape, strides, data);
    }
    operator view_t() {
        return view();
    }

    using const_view_t = tensor_view<const T, NDIMS>;
    const_view_t view() const {
        return tensor_view<const T, NDIMS>(shape, strides, data);
    }
    operator const_view_t() const {
        return view();
    }

    T& operator[] (std::array<int, NDIMS> idx) { return view()[idx]; }
    T& at(std::array<int, NDIMS> idx) { return view().at(idx); }
    const T& operator[] (std::array<int, NDIMS> idx) const { return view()[idx]; }
    const T& at(std::array<int, NDIMS> idx) const { return view().at(idx); }

    template <int D = NDIMS>
    typename std::enable_if<(0 < D), tensor_view<T, NDIMS-1>>::type operator[] (int idx) {
        return view()[idx];
    }
    template <int D = NDIMS>
    typename std::enable_if<(0 < D), tensor_view<T, NDIMS-1>>::type at(int idx) {
        return view().at(idx);
    }

    template <int D = NDIMS>
    typename std::enable_if<(0 < D), tensor_view<const T, NDIMS-1>>::type operator[] (int idx) const {
        return view()[idx];
    }
    template <int D = NDIMS>
    typename std::enable_if<(0 < D), tensor_view<const T, NDIMS-1>>::type at(int idx) const {
        return view().at(idx);
    }

    template <int D = NDIMS>
    typename std::enable_if<(0 == D), T&>::type operator * () {
        return *view();
    }
    template <int D = NDIMS>
    typename std::enable_if<(0 == D), const T&>::type operator * () const {
        return *view();
    }
};

#include<algorithm>
#include<complex>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<stdint.h>
#include<vector>

#ifdef LOCAL
#include "dbg.h"
#else
#define dbg(...)
#endif

using namespace std;

const int64_t INF = (int64_t) 1e18 + 777;
const int64_t mINF = (int64_t) 1e9 + 777;
const int64_t MOD = (int64_t) 1e9 + 7;

int getID(char c)
{
    if(c == 'R') return 0;
    if(c == 'G') return 1;
    if(c == 'Y') return 2;
    return -1;
}

struct Solution
{
	Solution() {}

	void solve()
	{
        int n;
        string s;
        cin >> n >> s;
        int k = 3;
        vector<vector<int> > colors(k);

        // ???
        for (int i = 0; i < k; i++) {
            colors.reserve(n);
        }

        vector<vector<int> > prefix(k, vector<int>(n + 1, 0));

        for(int i = 0; i < n; i++)
        {
            int x = getID(s[i]);
            colors[x].push_back(i);
            prefix[x][i + 1] = 1;
        }

        for(int i = 0; i < k; i++)
        {
            colors[i].push_back(n);
            // sort(colors[i].begin(), colors[i].end());

            for(int j = 1; j <= n; j++)
            {
                prefix[i][j] += prefix[i][j - 1];
            }
        }

        int r = colors[0].size();
        int g = colors[1].size();
        int y = colors[2].size();
        // vector<vector<vector<vector<vector<int> > > > > dp(2, vector<vector<vector<vector<int> > > >(k, vector<vector<vector<int> > >(r, vector<vector<int> >(g, vector<int>(y, mINF)))));
        tensor<int, 5> dp({2, k, r, g, y}, mINF);

        if(r > 1) dp[{0, 0, 1, 0, 0}] = colors[0][0];
        if(g > 1) dp[{0, 1, 0, 1, 0}] = colors[1][0];
        if(y > 1) dp[{0, 2, 0, 0, 1}] = colors[2][0];
        int t = 1;
        for(int i = 1; i < n; i++)
        {
            int p = t ^ 1;
            for(int last = 0; last < k; last++)
            {
                for(int cr = 0; cr < r; cr++)
                {
                    for(int cg = 0; cg < g; cg++)
                    {
                        for(int cy = 0; cy < y; cy++)
                        {
                            if(dp[{p, last, cr, cg, cy}] == mINF) continue;

                            // red
                            // A = last B = now C = other
                            if(last != 0 && cr != r - 1)
                            {
                                int a = last;
                                int b = 0;
                                int c = 0;

                                int cur_a = 0;
                                int cur_c = 0;
                                int cur_b = colors[b][cr];
                                if(a == 1)
                                {
                                    c = 2;
                                    cur_a = colors[a][cg];
                                    cur_c = colors[c][cy];
                                }
                                else
                                {
                                    c = 1;
                                    cur_a = colors[a][cy];
                                    cur_c = colors[c][cg];
                                }

                                int cnt1 = prefix[a][cur_b + 1] - prefix[a][cur_a];
                                int cnt2 = prefix[c][cur_b + 1] - prefix[c][cur_c];
                                cnt1 = max(cnt1, 0); cnt2 = max(cnt2, 0);

                                int cost = cnt1 + cnt2;
                                dp[{t, b, cr + 1, cg, cy}] = min(dp[{t, b, cr + 1, cg, cy}], dp[{p, last, cr, cg, cy}] + cost); 
                            }

                            // green
                            if(last != 1 && cg != g - 1)
                            {
                                int a = last;
                                int b = 1;
                                int c = 0;

                                int cur_a = 0;
                                int cur_c = 0;
                                int cur_b = colors[b][cg];
                                if(a == 0)
                                {
                                    c = 2;
                                    cur_a = colors[a][cr];
                                    cur_c = colors[c][cy];
                                }
                                else
                                {
                                    c = 0;
                                    cur_a = colors[a][cy];
                                    cur_c = colors[c][cr];
                                }

                                int cnt1 = prefix[a][cur_b + 1] - prefix[a][cur_a];
                                int cnt2 = prefix[c][cur_b + 1] - prefix[c][cur_c];
                                cnt1 = max(cnt1, 0); cnt2 = max(cnt2, 0);
                                int cost = cnt1 + cnt2;
                                dp[{t, b, cr, cg + 1, cy}] = min(dp[{t, b, cr, cg + 1, cy}], dp[{p, last, cr, cg, cy}] + cost); 
                            }

                            // yellow
                            if(last != 2 && cy != y - 1)
                            {
                                int a = last;
                                int b = 2;
                                int c = 0;

                                int cur_a = 0;
                                int cur_c = 0;
                                int cur_b = colors[b][cy];
                                if(a == 0)
                                {
                                    c = 1;
                                    cur_a = colors[a][cr];
                                    cur_c = colors[c][cg];
                                }
                                else
                                {
                                    c = 0;
                                    cur_a = colors[a][cg];
                                    cur_c = colors[c][cr];
                                }

                                int cnt1 = prefix[a][cur_b + 1] - prefix[a][cur_a];
                                int cnt2 = prefix[c][cur_b + 1] - prefix[c][cur_c];
                                cnt1 = max(cnt1, 0); cnt2 = max(cnt2, 0);

                                int cost = cnt1 + cnt2;
                                dp[{t, b, cr, cg, cy + 1}] = min(dp[{t, b, cr, cg, cy + 1}], dp[{p, last, cr, cg, cy}] + cost); 
                            }
                        }
                    }
                }
            }

            t ^= 1;
            for(int last = 0; last < k; last++)
            {
                for(int cr = 0; cr < r; cr++)
                {
                    for(int cg = 0; cg < g; cg++)
                    {
                        for(int cy = 0; cy < y; cy++)
                        {
                            dp[{p, last, cr, cg, cy}] = mINF;
                        }
                    }
                }
            }
        }

        int ans = mINF;
        for(int last = 0; last < k; last++)
        {
            ans = min(ans, dp[{t ^ 1, last, r - 1, g - 1, y - 1}]);
        }
        if(ans == mINF) ans = -1;
        cout << ans << "\n";
	}

	int modadd(int a, int b)
	{
		int res = a + b;
		if(res >= MOD) res -= MOD;
		return res;
	}

	int modmul(int a, int b)
	{
		return (1LL * a * b) % MOD;
	}
};

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
	int t = 1;
	//cin >> t;
	for(int i = 0; i < t; i++)
	{
		Solution().solve();
	}
	return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...