Submission #800628

#TimeUsernameProblemLanguageResultExecution timeMemory
800628thimote75Virus Experiment (JOI19_virus)C++14
6 / 100
2070 ms5328 KiB


#include <bits/stdc++.h>

using namespace std;

using bdata = vector<bool>;

using idata = vector<int>;
using igrid = vector<idata>;
using ispac = vector<igrid>;

string to_string(string s) { return s; }
template <typename T> string to_string(T v) {
	bool first = true;
	string res = "[";
	for (const auto &x : v) {
		if (!first)
			res += ", ";
		first = false;
		res += to_string(x);
	}
	res += "]";
	return res;
}

template <typename A, typename B>
string to_string(pair<A, B> p) {
  return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}

void dbg_out() { cout << endl; }
template <typename Head, typename... Tail> void dbg_out(Head H, Tail... T) {
	cout << ' ' << to_string(H);
	dbg_out(T...);
}

#ifdef DEBUG
#define dbg(...) cout << "(" << #__VA_ARGS__ << "):", dbg_out(__VA_ARGS__)
#else
#define dbg(...)
#endif

int R, C;

const int MASK_S = 1;
const int MASK_N = 2;
const int MASK_W = 4;
const int MASK_E = 8;

idata U;
int max_buffer[16];
bool check_road (idata &visited, int stage, int u) {
    if (U[u] == 0) return false;

    int S = u + C;
    int N = u - C;
    int W = u % C == 0     ? - 1 : u - 1;
    int E = u % C == C - 1 ? - 1 : u + 1;

    bool hS = S >= 0 && S < R * C ? visited[S] == stage : false;
    bool hN = N >= 0 && N < R * C ? visited[N] == stage : false;
    bool hW = W >= 0 && W < R * C ? visited[W] == stage : false;
    bool hE = E >= 0 && E < R * C ? visited[E] == stage : false;

    for (int m = 1; m < 16; m ++) {
        if (U [u] > max_buffer[m]) continue ;

        if ((m & MASK_S) != 0 && (!hS)) continue ;
        if ((m & MASK_N) != 0 && (!hN)) continue ;
        if ((m & MASK_W) != 0 && (!hW)) continue ;
        if ((m & MASK_E) != 0 && (!hE)) continue ;

        return true;
    }

    return false;
}

struct Mare {
    set<int> cases;
    int center;

    bool is_in (int x) {
        return cases.find(x) != cases.end();   
    }
    void merge (Mare *other) {
        if (cases.size() < other->cases.size()) cases.swap(other->cases);

        for (int u : other->cases) cases.insert(u);
    }
    bool operator< (const Mare &right) const {
        if (cases.size() == right.cases.size()) return center < right.center;
        return cases.size() < right.cases.size();
    }
    bool operator== (const Mare &right) const {
        return center == right.center;
    }
};

using vMare = vector<Mare*>;
using sMare = set<Mare*>;

struct UFD {
    vMare mares;
    sMare sorted_mares;
    idata parents;

    int rem () {
        return sorted_mares.size();
    }
    Mare* pop () {
        Mare* mare = *sorted_mares.begin();
        sorted_mares.erase(mare);

        return mare;
    }

    UFD () = default;
    UFD (int size) {
        mares.resize(size);
        for (int i = 0; i < size; i ++) {
            mares[i] = new Mare();
            mares[i]->cases.insert(i);
            mares[i]->center = i;

            sorted_mares.insert(mares[i]);
        }

        parents.resize(size);
        iota(parents.begin(), parents.end(), 0);
    }

    int boss (int x) {
        if (parents[x] != x)
            parents[x] = boss(parents[x]);
        return parents[x];
    }
    void merge (int a, int b) {
        a = boss(a); b = boss(b);
        if (a == b) return ;

        parents[b] = a;

        sorted_mares.erase(mares[a]);
        sorted_mares.erase(mares[b]);

        mares[a]->merge(mares[b]);
        sorted_mares.insert(mares[a]);
    }
};

int solve_buffer (bdata &values) {
    int r = 0;
    int l = 0;
    int c = 0;

    for (bool u : values) {
        if (u) {
            if (l == 0) { l = 1; c = 0; }

            c ++;
            r = max(r, c);
        } else l = 0;
    }
    for (bool u : values) {
        if (u) {
            if (l == 0) { l = 1; c = 0; }

            c ++;
            r = max(r, c);
        } else l = 0;
    }

    return r;
}

UFD ufd;

idata visited;
int stage = 0;
pair<int, int> find_outside (int x) {
    if (U[x] == 0) return { -1, 1e9 };
    int start = x;
    stage ++;
    
    queue<int> q;
    visited[start] = stage;
    q.push(start);

    int cnt = 0;

    while (q.size() != 0) {
        int curr = q.front(); q.pop();
        //dbg(curr);

        cnt ++;

        for (int adjacent : { 
                curr - C, 
                curr + C, 
                curr % C == 0 ? - 1 : curr - 1, 
                curr % C == C + 1 ? - 1 : curr + 1
            }) {
            if (adjacent < 0 || adjacent >= R * C) continue ;
            //dbg(adjacent);
            //dbg(visited[adjacent]);
            //dbg(stage);
            //dbg((int) (visited[adjacent] == stage));

            if (visited[adjacent] == stage) continue ;

            //dbg((int) (check_road(visited, stage, adjacent)));
            if (!check_road(visited, stage, adjacent)) continue ;

            //dbg((int) (mare.is_in(adjacent)));
            q.push(adjacent);
            visited[adjacent] = stage;
        }
    }

    return { -1, cnt };
}

int main () {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int T; cin >> T;
    cin >> R >> C;

    string buffer;
    cin >> buffer;

    bdata values(T);
    for (int m = 1; m < 16; m ++) {
        for (int i = 0; i < T; i ++) {
            values[i] = false;

            if (buffer[i] == 'S' && (0 != (m & MASK_S))) values[i] = true;
            if (buffer[i] == 'N' && (0 != (m & MASK_N))) values[i] = true;
            if (buffer[i] == 'W' && (0 != (m & MASK_W))) values[i] = true;
            if (buffer[i] == 'E' && (0 != (m & MASK_E))) values[i] = true;
        }

        max_buffer[m] = solve_buffer(values);
        if (max_buffer[m] > T) max_buffer[m] = 1e9;
    }

    U.resize(R * C);

    for (int r = 0; r < R; r ++) {
        for (int c = 0; c < C; c ++) {
            cin >> U[r * C + c];
        }
    }

    visited.resize(R * C);

    int res = 1e9;
    int cnt = 0;
    for (int a = 0; a < R * C; a ++) {
        int size = find_outside( a ).second;

        if (size > res) continue ;
        if (size < res) cnt = 0;

        res = size; cnt ++;
    }

    cout << res << "\n" << cnt << "\n";
}

#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...