#include <bits/stdc++.h>
#define rep(a,b,c) for(auto a = (b); a != (c); a++)
#define repD(a,b,c) for(auto a = (b); a != (c); a--)
#define repIn(a, b) for(auto& a : (b))
#define repIn2(a, b, c) for(auto& [a, b] : c)
#define ll long long
#define pb push_back
constexpr bool dbg = 1;
#define DEBUG if constexpr(dbg)
#define DC DEBUG std::cerr
#define eol std::endl
using namespace std;
constexpr int maxn = 1e6 + 7, maxLog = 23, inf = 1e9 + 8;
int h, w, q, n;
vector<int> graf[maxn];
int component[maxn], top[maxn], bottom[maxn];
int jp[maxn][maxLog];
pair<int, pair<int, int>> jp2[maxn][maxLog]; // { jump 2^j , { jump 2^j - 1 , jump 2^j + 1 } }
int rowCosts[maxn];
bool twos;
int cToRow1[maxn], cToRow2[maxn], rowToC[maxn];
int secondRTC[maxn];
int lowestSon1[maxn], lowestSon2[maxn];
bool cmpBottom(int a, int b) {
return bottom[a] < bottom[b];
}
bool cmpTop(int a, int b) {
return top[a] < top[b];
}
void input() {
scanf("%d%d%d", &h, &w, &q);
char c;
rep(i, 0, h) rep(j, 0, w - 1) scanf(" %c", &c), (c == '1' ? graf[i * w + j].pb(i * w + j + 1), graf[i * w + j + 1].pb(i * w + j), 0 : 0);
rep(i, 0, h - 1) rep(j, 0, w) scanf(" %c", &c), (c == '1' ? graf[i * w + j].pb(i * w + j + w), graf[i * w + j + w].pb(i * w + j), 0 : 0);
rep(i, 0, h) scanf("%d", rowCosts + i), twos = twos || (rowCosts[i] == 2);
}
void dfsComponents(int v, int c) {
component[v] = c;
top[c] = min(top[c], v / w);
bottom[c] = max(bottom[c], v / w);
repIn(u, graf[v]) if (!component[u]) dfsComponents(u, c);
}
void calcComponents() {
top[0] = bottom[0] = -1;
DC << "Components: " << eol;
rep(i, 0, h) rep(j, 0, w) if (!component[i * w + j]) {
n++;
top[n] = bottom[n] = i;
dfsComponents(i * w + j, n);
DC << " comp " << n << " from " << i << ' ' << j << " -> top " << top[n] << " bottom " << bottom[n] << eol;
}
}
void calcLowest() {
rep(i, 1, n + 1) cToRow1[i] = cToRow2[i] = -1;
repD(i, h - 1, -1) {
rep(j, 0, w) {
auto c = component[i * w + j];
if (rowToC[i] == 0 || bottom[c] > bottom[rowToC[i]]) secondRTC[i] = rowToC[i], rowToC[i] = c;
else if (secondRTC[i] == 0 || bottom[c] > bottom[secondRTC[i]]) secondRTC[i] = c;
if (rowCosts[i] == 1) if (cToRow1[c] == -1) cToRow1[c] = i;
if (rowCosts[i] == 2) if (cToRow2[c] == -1) cToRow2[c] = i;
}
}
//return;
DEBUG {
DC << "Component to row: " << eol;
rep(i, 1, n + 1) DC << " " << i << ": 1 -> " << cToRow1[i] << " 2 -> " << cToRow2[i] << eol;
DC << "Row to component: " << eol;
rep(i, 0, h) DC << " " << i << " -> " << rowToC[i] << eol;
}
}
void calcLowestSon() {
rep(i, 1, n + 1) lowestSon1[i] = (cToRow1[i] == -1 || bottom[rowToC[cToRow1[i]]] <= bottom[i] ? 0 : rowToC[cToRow1[i]]), lowestSon2[i] = (cToRow2[i] == -1 || bottom[rowToC[cToRow2[i]]] <= bottom[i] ? 0 : rowToC[cToRow2[i]]);
// return;
DEBUG {
DC << "LowestSons: " << eol;
rep(i, 1, n + 1) DC << " " << i << " ls1 " << lowestSon1[i] << " ls2 " << lowestSon2[i] << eol;
}
}
void calcJP() {
rep(i, 1, n + 1) jp[i][0] = lowestSon1[i];
rep(k, 1, maxLog) rep(i, 1, n + 1) jp[i][k] = jp[jp[i][k - 1]][k - 1];
}
pair<int, int> jump(int v, int u) {
DC << "jump " << v << ' ' << u << eol << ' ';
int ans = 0;
repD(k, maxLog - 1, -1) if (jp[v][k] && bottom[jp[v][k]] < top[u]) {
v = jp[v][k], ans += 1 << k;
DC << v << "(" << (1 << k) << ") ";
}
DC << eol;
return {v, ans};
}
int query(vector<int>& V) {
int ans = 0;
if(!twos) rep(i, 1, (int)V.size()) {
ranges::sort(V, cmpBottom);
int last = -1;
int v = V[0];
const auto& u = V[i];
DC << "Jumping from " << v << " to " << u << " ; last = " << last << eol;
if (v == u) DC << " skip" << eol;
if (v == u) continue;
if (last >= top[u] && last <= bottom[u]) DC << " skip" << eol;
if (last >= top[u] && last <= bottom[u]) continue;
if (v == 0) return -1;
if (bottom[v] >= top[u]) {
if (bottom[u] >= bottom[v]) last = (cToRow1[v] >= top[u]) ? cToRow1[v] : cToRow2[v];
else last = (cToRow1[u] >= top[v]) ? cToRow1[u] : cToRow2[u];
v = rowToC[last];
ans += rowCosts[last];
DC << " zachodza" << eol;
continue;
}
auto [vv, cost] = jump(v, u);
v = lowestSon1[vv], ans += cost;
if (top[u] > bottom[v]) return -1;
ans += 2;
if (bottom[u] >= bottom[v]) {
last = bottom[v];
v = lowestSon1[v];
}
else {
last = bottom[u];
v = lowestSon1[u];
}
}
if(twos) {
ranges::sort(V, cmpTop);
vector<pair<int, int>> dp;
vector<int> tmp;
rep(i, 0, (int)V.size()) if(((!i || V[i - 1] != V[i]) && (i == (int)V.size() - 1 || V[i + 1] != V[i])) || (i && V[i - 1] == V[i] && (i == (int)V.size() - 1 || V[i + 1] != V[i]))) tmp.pb(V[i]);
swap(tmp, V);
DC << " V: ";
repIn(i, V) DC << i << ' ';
DC << eol;
dp.pb({1, V[0]});
while(!dp.empty() && dp.back().first != (int)V.size()) {
if(dp.size() > 2 && dp.back() == dp[dp.size() - 3] && dp.back() == dp[dp.size() - 2]) { dp.clear(); break; }
pair<int, int> toPb = {-1, -1};
auto [lastVi, lastAll] = dp.back();
DC << " dp[" << dp.size() - 1 << "] = {" << lastVi << ' ' << lastAll << "}" << eol;
auto lastV = V[lastVi];
auto topNxtV = top[lastV];
auto botNxtV = bottom[lastV];
auto botAll = bottom[lastAll];
if(topNxtV <= botAll) {
// use lowest available to get as many from V as possible
int myRow = -1;
if(botNxtV <= botAll) myRow = cToRow1[lastV];
else myRow = cToRow1[lastAll];
if(myRow >= 0) {
while(lastVi < (int)V.size() && top[V[lastVi]] <= myRow && bottom[V[lastVi]] >= myRow) lastVi++;
toPb = max(toPb, pair{lastVi, rowToC[myRow]});
}
}
// use lowest one to get to lower all
toPb = max(toPb, pair{dp.back().first, lowestSon1[lastAll]});
if(dp.size() == 1) {
dp.pb(toPb);
continue;
}
// same but move by two
lastVi = dp[dp.size() - 2].first, lastAll = dp[dp.size() - 2].second;
lastV = V[lastVi];
topNxtV = top[lastV];
botNxtV = bottom[lastV];
botAll = bottom[lastAll];
if(topNxtV <= botAll) {
// use lowest available to get as many from V as possible
int myRow = -1;
if(botNxtV <= botAll) myRow = cToRow2[lastV];
else myRow = cToRow2[lastAll];
if(myRow >= 0) {
while(lastVi < (int)V.size() && top[V[lastVi]] <= myRow && bottom[V[lastVi]] >= myRow) lastVi++;
toPb = max(toPb, pair{lastVi, rowToC[myRow]});
}
}
// use lowest one to get to lower all
toPb = max(toPb, pair{dp[dp.size() - 2].first, lowestSon2[lastAll]});
dp.pb(toPb);
}
if(!dp.empty()) DC << " dp[" << dp.size() - 1 << "] = {" << dp.back().first << ' ' << dp.back().second << "}" << eol;
ans = (int)dp.size() - 1;
}
return ans;
}
void processQueries() {
int t, a, b;
vector<int> V;
rep(i, 0, q) {
DC << "Query " << i << eol;
scanf("%d", &t);
V.resize(t);
rep(j, 0, t) scanf("%d%d", &a, &b), V[j] = component[(a - 1) * w + b - 1];
printf("%d\n", query(V));
}
}
int main() {
input();
twos=true;
calcComponents();
calcLowest();
calcLowestSon();
calcJP();
processQueries();
return 0;
}
Compilation message (stderr)
Main.cpp: In function 'void input()':
Main.cpp:39:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
39 | scanf("%d%d%d", &h, &w, &q);
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~
Main.cpp:41:40: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
41 | rep(i, 0, h) rep(j, 0, w - 1) scanf(" %c", &c), (c == '1' ? graf[i * w + j].pb(i * w + j + 1), graf[i * w + j + 1].pb(i * w + j), 0 : 0);
| ~~~~~^~~~~~~~~~~
Main.cpp:42:40: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
42 | rep(i, 0, h - 1) rep(j, 0, w) scanf(" %c", &c), (c == '1' ? graf[i * w + j].pb(i * w + j + w), graf[i * w + j + w].pb(i * w + j), 0 : 0);
| ~~~~~^~~~~~~~~~~
Main.cpp:43:23: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
43 | rep(i, 0, h) scanf("%d", rowCosts + i), twos = twos || (rowCosts[i] == 2);
| ~~~~~^~~~~~~~~~~~~~~~~~~~
Main.cpp: In function 'void processQueries()':
Main.cpp:216:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
216 | scanf("%d", &t);
| ~~~~~^~~~~~~~~~
Main.cpp:218:27: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
218 | rep(j, 0, t) scanf("%d%d", &a, &b), V[j] = component[(a - 1) * w + b - 1];
| ~~~~~^~~~~~~~~~~~~~~~
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |