This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
#pragma warning (disable: 4996)
// ==================================================================================================================================================== ãã®ä»–ã®é–¢æ•°
// ä½ç½® pos ã‹ã‚‰ x 手ã§ç§»å‹•ã§ãる最大ä½ç½®
int GetMaxPosition(int pos, int x, vector<vector<int>>& par) {
if (x == -1) return -50000;
vector<int> dp0(23, -1);
vector<int> dp1(23, -1);
dp0[22] = pos;
for (int i = 21; i >= 0; i--) {
if ((x / (1 << i)) % 2 == 0) {
dp0[i] = dp0[i + 1];
dp1[i] = dp1[i + 1];
continue;
}
if (dp0[i + 1] != -1) dp0[i] = max(dp0[i], par[3 * i + 1][dp0[i + 1]]);
if (dp1[i + 1] != -1) dp0[i] = max(dp0[i], par[3 * i + 0][dp1[i + 1]]);
if (dp0[i + 1] != -1) dp1[i] = max(dp1[i], par[3 * i + 2][dp0[i + 1]]);
if (dp1[i + 1] != -1) dp1[i] = max(dp1[i], par[3 * i + 1][dp1[i + 1]]);
}
return dp0[0];
}
// ä½ç½® pos ã‹ã‚‰ä½ç½® goal 以上ã¾ã§è¡ŒããŸã‚ã®æœ€å°ã‚³ã‚¹ãƒˆ
int GetMinCost(int pos, int goal, vector<vector<int>>& par) {
if (pos == -1) return 1000000000;
if (pos >= goal) return 0;
int cur1 = pos;
int cur2 = -1;
int ans = 0;
for (int i = 21; i >= 0; i--) {
int v1 = -1;
int v2 = -1;
if (cur1 != -1) v1 = max(v1, par[3 * i + 1][cur1]);
if (cur2 != -1) v1 = max(v1, par[3 * i + 0][cur2]);
if (cur1 != -1) v2 = max(v2, par[3 * i + 2][cur1]);
if (cur2 != -1) v2 = max(v2, par[3 * i + 1][cur2]);
if (v1 < goal && v2 < goal) {
cur1 = v1;
cur2 = v2;
ans += (1 << i);
}
}
if (cur1 != -1 && par[1][cur1] >= goal) return ans + 1;
if (cur2 != -1 && par[1][cur2] >= goal) return ans + 2;
if (cur1 != -1 && par[2][cur1] >= goal) return ans + 2;
return ans + 3;
}
// 極å°ãªåŒºé–“ã ã‘ã‚’å–り出ã™é–¢æ•°
vector<pair<int, int>> OnlyMinimal(vector<pair<int, int>> Ranges) {
for (int i = 0; i < Ranges.size(); i++) Ranges[i].first *= -1;
sort(Ranges.begin(), Ranges.end());
vector<pair<int, int>> Return;
int MinValue = (1 << 30);
for (int i = 0; i < Ranges.size(); i++) {
if (MinValue > Ranges[i].second) {
MinValue = Ranges[i].second;
Return.push_back(Ranges[i]);
}
}
for (int i = 0; i < Return.size(); i++) Return[i].first *= -1;
sort(Return.begin(), Return.end());
return Return;
}
// ä½ç½® pos を区間 [cl, cr] ã«ä¿®æ£
pair<int, int> FixPosition(int moto, int pos, int cl, int cr, int cost, vector<int>& C, vector<int>& NextCost1, vector<int>& NextCost2, vector<vector<int>>& par, vector<int>& UpLim) {
if (pos < cl) return make_pair(-1, 1000000000);
if (pos <= cr) return make_pair(pos, cost);
if (C[pos] == 1) {
int idx1 = NextCost1[cr];
int idx2 = NextCost2[cr];
int result = -1;
if (idx1 >= cl) result = max(result, idx1);
if (cost >= 2) {
int prepos = GetMaxPosition(moto, cost - 2, par);
int nexpos = UpLim[prepos];
if (nexpos >= cl && NextCost2[min(cr, nexpos)] >= cl) result = max(result, NextCost2[min(cr, nexpos)]);
}
if (result != -1) return make_pair(result, cost);
return make_pair(idx2, cost + 1);
}
return make_pair(NextCost2[cr], cost);
}
// ä½ç½® pos ã‹ã‚‰åŒºé–“ [cl, cr] ã«è¡ŒããŸã‚ã®æœ€å°ã‚³ã‚¹ãƒˆ
int RangeCost(int pos, int cl, int cr, vector<int>& C, vector<int>& NextCost1, vector<int>& NextCost2, vector<vector<int>>& par, vector<int>& UpLim) {
int base = GetMinCost(pos, cl, par);
int newpos = GetMaxPosition(pos, base, par);
pair<int, int> fixpos = FixPosition(pos, newpos, cl, cr, base, C, NextCost1, NextCost2, par, UpLim);
return fixpos.second;
}
// ==================================================================================================================================================== å•é¡Œã‚’解ã関数
vector<int> solve_subtask8(int H, int W, int Q, vector<vector<char>> A, vector<vector<char>> B, vector<int> C, vector<vector<pair<int, int>>> Query) {
// Step 1. 連çµæˆåˆ†ã‚’探ã™
vector<vector<int>> GroupID(H, vector<int>(W, -1));
int GroupCnt = 0;
for (int i = 0; i < H; i++) {
for (int j = 0; j < W; j++) {
if (GroupID[i][j] != -1) continue;
queue<pair<int, int>> Que;
Que.push(make_pair(i, j));
GroupID[i][j] = GroupCnt;
while (!Que.empty()) {
int px = Que.front().first;
int py = Que.front().second;
Que.pop();
if (px - 1 >= 0 && B[px - 1][py] == '1' && GroupID[px - 1][py] == -1) {
GroupID[px - 1][py] = GroupCnt;
Que.push(make_pair(px - 1, py));
}
if (px + 1 < H && B[px][py] == '1' && GroupID[px + 1][py] == -1) {
GroupID[px + 1][py] = GroupCnt;
Que.push(make_pair(px + 1, py));
}
if (py - 1 >= 0 && A[px][py - 1] == '1' && GroupID[px][py - 1] == -1) {
GroupID[px][py - 1] = GroupCnt;
Que.push(make_pair(px, py - 1));
}
if (py + 1 < W && A[px][py] == '1' && GroupID[px][py + 1] == -1) {
GroupID[px][py + 1] = GroupCnt;
Que.push(make_pair(px, py + 1));
}
}
GroupCnt += 1;
}
}
// Step 2. å„連çµæˆåˆ†ã«å¯¾å¿œã™ã‚‹åŒºé–“を求ã‚ã‚‹
vector<pair<int, int>> Range(GroupCnt, make_pair(100000000, -100000000));
for (int i = 0; i < H; i++) {
for (int j = 0; j < W; j++) {
Range[GroupID[i][j]].first = min(Range[GroupID[i][j]].first, i);
Range[GroupID[i][j]].second = max(Range[GroupID[i][j]].second, i);
}
}
// Step 3. å„地点ã®ç›´å‰ã®ã‚³ã‚¹ãƒˆ 1, 2 ã®ä½ç½®ã‚’計算
vector<int> NextCost1(H, -1);
vector<int> NextCost2(H, -1);
for (int i = 0; i < H; i++) {
if (i >= 1) {
NextCost1[i] = NextCost1[i - 1];
NextCost2[i] = NextCost2[i - 1];
}
if (C[i] == 1) NextCost1[i] = i;
if (C[i] == 2) NextCost2[i] = i;
}
// Step 4. 最大値を計算
vector<int> UpLim(H, -1);
for (int i = 0; i < H; i++) UpLim[i] = i;
for (pair<int, int> idx : Range) {
UpLim[idx.first] = max(UpLim[idx.first], idx.second);
}
for (int i = 1; i < H; i++) UpLim[i] = max(UpLim[i], UpLim[i - 1]);
// Step 5. ダブリングã®åˆæœŸåŒ–
// par[3*d+e][i] ã¯é ‚点 i ã‹ã‚‰ã‚³ã‚¹ãƒˆ 2^d+(e-1) ã§ã©ã“ã¾ã§è¡Œã‘ã‚‹ã‹
vector<vector<int>> par(66, vector<int>(H, -1));
for (int i = 0; i < H; i++) par[0][i] = i;
for (int i = 0; i < H; i++) par[1][i] = max(i, NextCost1[UpLim[i]]);
for (int i = 0; i < H; i++) {
int v1 = NextCost2[UpLim[i]];
int v2 = NextCost1[UpLim[i]];
int v3 = (v2 == -1 ? -1 : NextCost1[UpLim[v2]]);
par[2][i] = max({ i, v1, v3 });
}
// Step 6. ダブリングã®è¨ˆç®—
for (int d = 3; d < 66; d += 3) {
for (int i = 0; i < H; i++) {
par[d + 0][i] = max({ par[d - 3][par[d - 2][i]], par[d - 2][par[d - 3][i]] });
par[d + 1][i] = max({ par[d - 3][par[d - 1][i]], par[d - 2][par[d - 2][i]], par[d - 1][par[d - 3][i]] });
par[d + 2][i] = max({ par[d - 2][par[d - 1][i]], par[d - 1][par[d - 2][i]] });
}
}
// Step 7. å„クエリã«ãŠã‘ã‚‹ç”ãˆã‚’計算
vector<int> Answer(Q, -1);
for (int t = 0; t < Q; t++) {
vector<int> Groups;
for (pair<int, int> idx : Query[t]) Groups.push_back(GroupID[idx.first][idx.second]);
sort(Groups.begin(), Groups.end());
Groups.erase(unique(Groups.begin(), Groups.end()), Groups.end());
if (Groups.size() == 1) {
Answer[t] = 0;
}
else {
vector<pair<int, int>> List;
for (int idx : Groups) List.push_back(Range[idx]);
vector<pair<int, int>> Important = OnlyMinimal(List);
vector<int> dpval(Important.size(), 1000000000);
vector<int> dp0(Important.size(), -1);
vector<int> dp1(Important.size(), -1);
// åˆæœŸå€¤ã®è¨ˆç®—
if (NextCost1[Important[0].second] < Important[0].first) {
dpval[0] = 2;
dp0[0] = NextCost2[Important[0].second];
dp1[0] = -1;
}
else {
dpval[0] = 1;
dp0[0] = NextCost1[Important[0].second]; if (dp0[0] < Important[0].first) dp0[0] = -1;
dp1[0] = NextCost2[Important[0].second]; if (dp1[0] < Important[0].first) dp1[0] = -1;
}
// 動的計画法
for (int i = 1; i < Important.size(); i++) {
int cl = Important[i].first;
int cr = Important[i].second;
int cost1 = 1000000000; if (dp0[i - 1] != -1) cost1 = RangeCost(dp0[i - 1], cl, cr, C, NextCost1, NextCost2, par, UpLim);
int cost2 = 1000000000; if (dp1[i - 1] != -1) cost2 = RangeCost(dp1[i - 1], cl, cr, C, NextCost1, NextCost2, par, UpLim);
dpval[i] = min({ dpval[i], dpval[i - 1] + cost1, dpval[i - 1] + cost2 + 1 });
if (dpval[i] > 2 * H) break;
int pos1 = GetMaxPosition(dp0[i - 1], dpval[i] - (dpval[i - 1] + 0) + 0, par);
int pos2 = GetMaxPosition(dp1[i - 1], dpval[i] - (dpval[i - 1] + 1) + 0, par);
int pos3 = GetMaxPosition(dp0[i - 1], dpval[i] - (dpval[i - 1] + 0) + 1, par);
int pos4 = GetMaxPosition(dp1[i - 1], dpval[i] - (dpval[i - 1] + 1) + 1, par);
pair<int, int> fix1 = FixPosition(dp0[i - 1], pos1, cl, cr, dpval[i] - (dpval[i - 1] + 0) + 0, C, NextCost1, NextCost2, par, UpLim);
pair<int, int> fix2 = FixPosition(dp1[i - 1], pos2, cl, cr, dpval[i] - (dpval[i - 1] + 1) + 0, C, NextCost1, NextCost2, par, UpLim);
pair<int, int> fix3 = FixPosition(dp0[i - 1], pos3, cl, cr, dpval[i] - (dpval[i - 1] + 0) + 1, C, NextCost1, NextCost2, par, UpLim);
pair<int, int> fix4 = FixPosition(dp1[i - 1], pos4, cl, cr, dpval[i] - (dpval[i - 1] + 1) + 1, C, NextCost1, NextCost2, par, UpLim);
if (fix1.second + (dpval[i - 1] + 0) == dpval[i] + 0) dp0[i] = max(dp0[i], fix1.first);
if (fix1.second + (dpval[i - 1] + 0) == dpval[i] + 1) dp1[i] = max(dp1[i], fix1.first);
if (fix2.second + (dpval[i - 1] + 1) == dpval[i] + 0) dp0[i] = max(dp0[i], fix2.first);
if (fix2.second + (dpval[i - 1] + 1) == dpval[i] + 1) dp1[i] = max(dp1[i], fix2.first);
if (fix3.second + (dpval[i - 1] + 0) == dpval[i] + 0) dp0[i] = max(dp0[i], fix3.first);
if (fix3.second + (dpval[i - 1] + 0) == dpval[i] + 1) dp1[i] = max(dp1[i], fix3.first);
if (fix4.second + (dpval[i - 1] + 1) == dpval[i] + 0) dp0[i] = max(dp0[i], fix4.first);
if (fix4.second + (dpval[i - 1] + 1) == dpval[i] + 1) dp1[i] = max(dp1[i], fix4.first);
}
Answer[t] = dpval[Important.size() - 1];
if (Answer[t] > 2 * H) Answer[t] = -1;
}
}
// Step 8. ç”ãˆã‚’è¿”ã™
return Answer;
}
// ==================================================================================================================================================== 入出力
int main() {
// 入力
int H, W, Q;
scanf("%d%d%d", &H, &W, &Q);
vector<vector<char>> A(H, vector<char>(W - 1, 0));
vector<vector<char>> B(H - 1, vector<char>(W, 0));
vector<vector<pair<int, int>>> Query(Q, vector<pair<int, int>>(0, make_pair(0, 0)));
vector<int> C(H, 0);
for (int i = 0; i < H; i++) {
for (int j = 0; j < W - 1; j++) cin >> A[i][j];
}
for (int i = 0; i < H - 1; i++) {
for (int j = 0; j < W; j++) cin >> B[i][j];
}
for (int i = 0; i < H; i++) cin >> C[i];
for (int i = 0; i < Q; i++) {
int t, x, y; scanf("%d", &t);
for (int j = 0; j < t; j++) {
scanf("%d%d", &x, &y); x--; y--;
Query[i].push_back(make_pair(x, y));
}
}
// 出力
vector<int> Answer = solve_subtask8(H, W, Q, A, B, C, Query);
for (int i = 0; i < Q; i++) printf("%d\n", Answer[i]);
return 0;
}
Compilation message (stderr)
Main.cpp:6: warning: ignoring '#pragma warning ' [-Wunknown-pragmas]
6 | #pragma warning (disable: 4996)
|
Main.cpp: In function 'std::vector<std::pair<int, int> > OnlyMinimal(std::vector<std::pair<int, int> >)':
Main.cpp:57:20: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
57 | for (int i = 0; i < Ranges.size(); i++) Ranges[i].first *= -1;
| ~~^~~~~~~~~~~~~~~
Main.cpp:61:20: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
61 | for (int i = 0; i < Ranges.size(); i++) {
| ~~^~~~~~~~~~~~~~~
Main.cpp:67:20: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
67 | for (int i = 0; i < Return.size(); i++) Return[i].first *= -1;
| ~~^~~~~~~~~~~~~~~
Main.cpp: In function 'std::vector<int> solve_subtask8(int, int, int, std::vector<std::vector<char> >, std::vector<std::vector<char> >, std::vector<int>, std::vector<std::vector<std::pair<int, int> > >)':
Main.cpp:217:22: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
217 | for (int i = 1; i < Important.size(); i++) {
| ~~^~~~~~~~~~~~~~~~~~
Main.cpp: In function 'int main()':
Main.cpp:254:7: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
254 | scanf("%d%d%d", &H, &W, &Q);
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~
Main.cpp:267:21: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
267 | int t, x, y; scanf("%d", &t);
| ~~~~~^~~~~~~~~~
Main.cpp:269:9: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
269 | scanf("%d%d", &x, &y); x--; y--;
| ~~~~~^~~~~~~~~~~~~~~~
# | 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... |