Submission #1019052

#TimeUsernameProblemLanguageResultExecution timeMemory
1019052andrei_iorgulescuMaze (JOI23_ho_t3)C++17
59 / 100
484 ms141480 KiB
#include <bits/stdc++.h> #pragma GCC optimize("O3,unroll-loops") #pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt") using namespace std; int inf = 1e9; int dl[] = {-1,0,1,0}; int dc[] = {0,1,0,-1}; int r,c,n; int xs,ys,xf,yf; vector<vector<char>>a; vector<vector<int>>d; pair<short int,int> new_cells[6000005],cells[6000005]; int ncs,cs; vector<vector<int>>s; vector<vector<short int>>ss; vector<int>ts; vector<short int>tss; int lgc,lgr; vector<vector<bool>> luat; void updates(int unde,int pos) { ts[unde]--; #pragma GCC ivdep for (int i = pos; i <= c; i += (i & -i)) s[unde][i]--; } void updatess(int unde,int pos) { tss[unde]--; #pragma GCC ivdep for (int i = pos; i <= r; i += (i & -i)) ss[unde][i]--; } int querys(int x,int y) { int rsp = 0; #pragma GCC ivdep for (int i = y; i > 0; i -= (i & -i)) rsp += s[x][i]; return rsp; } int queryss(int x,int y) { int rsp = 0; #pragma GCC ivdep for (int i = y; i > 0; i -= (i & -i)) rsp += ss[x][i]; return rsp; } int s_findnext(int x,int y) { int vv = querys(x,y - 1); if (vv == ts[x]) return -1; int sumaib = 0; int st = 0,pas = 1 << lgc; #pragma GCC ivdep while (pas != 0) { if (st + pas <= c and sumaib + s[x][st + pas] <= vv) { st += pas; sumaib += s[x][st]; } pas >>= 1; } return st + 1; } int ss_findnext(int x,int y) { int vv = queryss(x,y - 1); if (vv == tss[x]) return -1; int sumaib = 0; int st = 0,pas = 1 << lgr; #pragma GCC ivdep while (pas != 0) { if (st + pas <= r and sumaib + ss[x][st + pas] <= vv) { st += pas; sumaib += ss[x][st]; } pas >>= 1; } return st + 1; } void dfs(int x,int y) { //cout << "sus" << x << ' ' << y << endl; for (int i = 0; i < 4; i++) { int nx = x + dl[i],ny = y + dc[i]; if (nx >= 1 and nx <= r and ny >= 1 and ny <= c and d[nx][ny] == inf and a[nx][ny] == '.') { d[nx][ny] = d[x][y]; //s[nx].erase(ny); //ss[ny].erase(nx); updates(nx,ny); updatess(ny,nx); cells[cs++] = {nx,ny}; dfs(nx,ny); } } } int dgl; void orizontala(int x,int y1,int y2) { //cout << "h" << x << ' ' << y1 << ' ' << y2 << endl; #pragma GCC ivdep while (true) { /*auto it = s[x].lower_bound(y1); if (it == s[x].end() or *it > y2) return; d[x][*it] = dgl; new_cells.push_back({x,*it}); s[x].erase(*it); ss[*it].erase(x);*/ int it = s_findnext(x,y1); if (it == -1 or it > y2) return; d[x][it] = dgl; new_cells[ncs++] = {x,it}; updates(x,it); updatess(it,x); } } void verticala(int y,int x1,int x2) { //cout << "v" << y << ' ' << x1 << ' ' << x2 << endl; #pragma GCC ivdep while (true) { /*auto it = ss[y].lower_bound(x1); if (it == ss[y].end() or *it > x2) return; d[*it][y] = dgl; new_cells.push_back({*it,y}); ss[y].erase(*it); s[*it].erase(y);*/ int it = ss_findnext(y,x1); if (it == -1 or it > x2) return; d[it][y] = dgl; new_cells[ncs++] = {it,y}; updatess(y,it); updates(it,y); } } vector<int> dll; vector<int> dcc; void baga(int x,int y) { luat[x][y] = true; //cout << "bagat" << ' ' << x << ' ' << y << endl; dgl = d[x][y] + 1; if (abs(x - xf) <= n and abs(y - yf) <= n and abs(x - xf) + abs(y - yf) < 2 * n) { d[xf][yf] = min(d[xf][yf],1 + d[x][y]); return; } int x1 = x - n,x2 = x + n,y1 = y - n,y2 = y + n; ///teoretic pot tot patratul (x1,y1,x2,y2) fara colturi, daca ies din matrice ayaye ///pot sa iau intersectia dreptunghiurilor (x1,y1,x2,y2) cu matricea si daca e tai colturile x1 = max(x1,1); x2 = min(x2,r); y1 = max(y1,1); y2 = min(y2,c); //cout << x1 << ' ' << x2 << ' ' << y1 << ' ' << y2 << endl; bool sus = false,jos = false,dreapta = false,stanga = false; if (x != 1 and luat[x - 1][y]) sus = true; if (x != r and luat[x + 1][y]) jos = true; if (y != 1 and luat[x][y - 1]) stanga = true; if (y != c and luat[x][y + 1]) dreapta = true; if (!stanga or !dreapta) { if (x1 != x - n) { orizontala(x1,y1,y2); } else { int y1r = y1,y2r = y2; if (y1 == y - n) y1r++; if (y2 == y + n) y2r--; orizontala(x1,y1r,y2r); } if (x2 != x + n) { orizontala(x2,y1,y2); } else { int y1r = y1,y2r = y2; if (y1 == y - n) y1r++; if (y2 == y + n) y2r--; orizontala(x2,y1r,y2r); } } if (!sus or !jos) { if (y1 != y - n) { verticala(y1,x1,x2); } else { int x1r = x1,x2r = x2; if (x1 == x - n) x1r++; if (x2 == x + n) x2r--; verticala(y1,x1r,x2r); } if (y2 != y + n) { verticala(y2,x1,x2); } else { int x1r = x1,x2r = x2; if (x1 == x - n) x1r++; if (x2 == x + n) x2r--; verticala(y2,x1r,x2r); } } for (int i = 0; i < 8; i++) { int nx = x + dll[i],ny = y + dcc[i]; if (nx < 1) nx = 1; if (nx > r) nx = r; if (ny < 1) ny = 1; if (ny > c) ny = c; bool yea = true; if ((i == 0 or i == 1) and (sus or stanga)) yea = false; if ((i == 2 or i == 3) and (sus or dreapta)) yea = false; if ((i == 4 or i == 5) and (jos or dreapta)) yea = false; if ((i == 6 or i == 7) and (jos or stanga)) yea = false; if (yea and d[nx][ny] == inf) { d[nx][ny] = dgl; new_cells[ncs++] = {nx,ny}; updates(nx,ny); updatess(ny,nx); } } } int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); cin >> r >> c >> n >> xs >> ys >> xf >> yf; a.resize(r + 1); s.resize(r + 1); ss.resize(c + 1); ts.resize(r + 1); tss.resize(c + 1); dll = {-(n - 1),-n,-n,-(n - 1),(n - 1),n,n,(n - 1)}; dcc = {-n,-(n - 1),n - 1,n,n,n - 1,-(n - 1),-n}; lgc = __lg(c); lgr = __lg(r); for (int i = 1; i <= r; i++) ts[i] = c; for (int i = 1; i <= c; i++) tss[i] = r; for (int i = 1; i <= r; i++) s[i].resize(c + 1); for (int i = 1; i <= c; i++) ss[i].resize(r + 1); luat.resize(r + 1); for (int i = 1; i <= r; i++) luat[i].resize(c + 1); for (int i = 1; i <= r; i++) { for (int j = 1; j <= c; j++) { s[i][j] = (j & -j); ss[j][i] = (i & -i); } } for (int i = 1; i <= r; i++) { a[i].resize(c + 1); for (int j = 1; j <= c; j++) cin >> a[i][j]; } d.resize(r + 1); for (int i = 1; i <= r; i++) d[i].resize(c + 1); for (int i = 1; i <= r; i++) for (int j = 1; j <= c; j++) d[i][j] = 1e9; new_cells[ncs++] = {xs,ys}; d[xs][ys] = 0; updates(xs,ys); updatess(ys,xs); while (true) { //cout << endl; //for (auto it : new_cells) // cout << "nc" << ' ' << it.first << ' ' << it.second << ' ' << d[it.first][it.second] << endl; //cells = new_cells; cs = ncs; for (int i = 0; i < cs; i++) cells[i] = new_cells[i]; for (int i = 0; i < ncs; i++) dfs(new_cells[i].first,new_cells[i].second); if (d[xf][yf] != inf) break; ncs = 0; for (int i = 0; i < cs; i++) baga(cells[i].first,cells[i].second); if (d[xf][yf] != inf) break; } cout << d[xf][yf]; return 0; } /** din (i,j) pot merge ori intr-un vecin care e si el alb as mai putea merge in patratul de latura 2n + 1 centrat in (i,j) fara colturile lui acum, faza funny e ca nu prea ma intereseaza de mersul inauntrul formei ci doar pe marini, unless este celula de finish in interior asa ca, ori e celula de finish in interior si zic direct gen "boss, dute in aia", ori pun cu cost + 1 celulele de pe margini acum, ca sa gasesc celulele de pe margini nevizitate inca, trebuie doar sa vad pe niste bucati de linii / coloane care mai sunt alive asta pot cu un set, dar cu constanta aia :skull: mai bine nu, deci bag aib si cb pe aib Acum, cum imi fac dfs-ul ca sa nu iasa nimic dubios In etape, cat timp n-am ajuns la finish, mai intai imi iau celulele cu care n-am trecut prin faza 1 si le dau fill cat au in jur 0 Iar in faza 2 iau celulele care n-au trecut prin faza asta si le fac kinda patratul, iau alea de pe margini etc **/ ///hocus pocus ca sa treaca
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...