Advertisement
willy108

Robots on Grids

Mar 23rd, 2022
851
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.37 KB | None | 0 0
  1.  
  2. #pragma GCC optimize("Ofast")
  3. #pragma GCC optimize("unroll-loops")
  4. #pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
  5. //stupid robot grid
  6.  
  7. //misaka will carry me to master
  8.  
  9. #include <iostream>
  10. #include <cstdio>
  11. #include <cstring>
  12. #include <cmath>
  13. #include <utility>
  14. #include <cassert>
  15. #include <algorithm>
  16. #include <vector>
  17. #include <functional>
  18. #include <numeric>
  19. #include <set>
  20. #include <map>
  21. #include <queue>
  22. #include <bitset>
  23.  
  24. #define ll long long
  25. #define lb long double
  26. #define sz(vec) ((int)(vec.size()))
  27. #define all(x) x.begin(), x.end()
  28. #define pb push_back
  29. #define mp make_pair
  30. #define ff first
  31. #define ss second
  32. //probably useful
  33.  
  34. const lb eps = 1e-9;
  35. const ll mod = 1e9 + 7, ll_max = 1e18;
  36. //const ll mod = (1 << (23)) * 119 +1;
  37. const int MX = 4e5 +10, int_max = 0x3f3f3f3f;
  38. const int SEG = (5e4*4) + (5e4*3 + 1e5 +1)*2 +100;
  39. using namespace std;
  40.  
  41.  
  42. struct disc{
  43.     vector<int> vals;
  44.     void add(int x){
  45.         vals.pb(x);
  46.     }
  47.     void norm(){
  48.         sort(all(vals));
  49.         vals.resize(unique(all(vals)) - vals.begin());
  50.     }
  51.     int gind(int x){
  52.         return (lower_bound(all(vals), x) - vals.begin()) +1;
  53.     }
  54.     int zz(){
  55.         return sz(vals);
  56.     }
  57. } xes, yes;
  58. //using namespace disc;
  59. //parallel to x axis is 0
  60. //            y axis is 1
  61. struct segment{
  62.     int dir, pos, l, r;
  63.     int ind;
  64.     segment(){}
  65.     segment(int a, int b, int c, int d){
  66.         dir = a, pos = b, l = c, r = d;
  67.     }
  68.     int left() const{
  69.         return (dir) ? pos : l;
  70.     }
  71.     int down() const{
  72.         return (dir) ? l : pos;
  73.     }
  74.     bool operator < (const segment& b) const{
  75.         if(*this == b) return 0;
  76.         int lhs = left();
  77.         int rhs = b.left();
  78.         if(lhs == rhs){
  79.         if(dir == b.dir){
  80.                 if(dir == 0){
  81.                     return (l == b.l) ? (pos < b.pos) : (l < b.l);
  82.                 }else{
  83.                     return (pos == b.pos) ? (l < b.l) :(pos < b.pos);
  84.                 }
  85.             }else{
  86.                 return dir < b.dir;
  87.             }
  88.         }else{
  89.             return lhs < rhs;
  90.         }
  91.     }
  92.     bool operator == (const segment& b) const{
  93.         return dir == b.dir && pos == b.pos && l == b.l && r == b.r;
  94.     }
  95.     void pr(){
  96.         cout << dir << " " << pos << " " << l << " " << r << " " << ind <<  "\n";
  97.     }
  98. } seg[SEG];
  99.  
  100.  
  101. const int NN = MX*30; //yes
  102.  
  103. /** pst **/
  104. int lc[NN], rc[NN];
  105. int IND = 1, sind = 1;
  106. int n, m, K, q, s;
  107. vector<pair<int, int>> adj[SEG];
  108.  
  109.  
  110. void dup(int& k){
  111.     IND++;
  112.     lc[IND] = lc[k];
  113.     rc[IND] = rc[k];
  114.     k = IND;
  115. }
  116.  
  117. void U(int p, int v, int& k, int L, int R){
  118.     //assert(k >= 0);
  119.     if(R <= L || p < L || R <= p) return ;
  120.     dup(k);
  121.     if(L + 1 == R){
  122.         assert(L == p);
  123.         lc[k] = v;
  124.         rc[k] = -1;
  125.         return ;
  126.     }
  127.     int mid = (L + R)/2;
  128.     if(p < mid) U(p, v, lc[k], L, mid);
  129.     else U(p, v, rc[k], mid, R);
  130.     //no pull needed i think
  131. }
  132.  
  133. void add_edge(int a, int b, int c){
  134.     if(a == 0 || b==0) return;
  135.         adj[a].pb(mp(b, c));
  136. }
  137.  
  138.  
  139. void Q(int qL, int qR, int e, int k, int L, int R){
  140.     if(qR <= L || R <= qL || R <= L || qR <= qL || k == 0) return ;
  141.     if(qL <= L && R <= qR){
  142.         //e.pb(k);
  143.         add_edge(e, k, 1);
  144.         return ;
  145.     }
  146.     int mid = (L + R)/2;
  147.     Q(qL, qR, e, lc[k], L, mid);
  148.     Q(qL, qR, e, rc[k], mid, R);
  149. }
  150.  
  151. /** relevant to problem **/
  152. #define pii pair<int, int>
  153. vector<pii> points, queries;
  154. pii source;
  155.  
  156. set<int> bl_x[SEG], bl_y[SEG];
  157. int dist[NN];
  158. bitset<NN> vis;
  159. int ans[MX];
  160.  
  161. const int drow[] = {0, 0, -1, 1};
  162. const int dcol[] = {-1, 1, 0, 0};
  163.  
  164.  
  165. segment make(int x, int y, int d){
  166.     if(d == 0){
  167.         int l = *prev(bl_y[y].lower_bound(x)), r = *bl_y[y].lower_bound(x);
  168.         l++, r--;
  169.         return segment(0, y, l, r);
  170.     }else{
  171.         int l = *prev(bl_x[x].lower_bound(y)), r = *bl_x[x].lower_bound(y);
  172.         l++, r--;
  173.         return segment(1, x, l, r);
  174.     }
  175. }
  176.  
  177. bool cmp(const segment& a, const segment& b){
  178.     int lhs = a.down();
  179.     int rhs = b.down();
  180.     if(lhs == rhs){
  181.         if(a.dir == b.dir){
  182.             if(a.dir == 1){
  183.                 return (a.l == b.l) ? (a.pos < b.pos) : (a.l < b.l);
  184.             }else{
  185.                 return (a.pos == b.pos) ? (a.l < b.l) :(a.pos < b.pos);
  186.             }
  187.         }else{
  188.             return a.dir > b.dir;
  189.         }
  190.     }else{
  191.         return lhs < rhs;
  192.     }
  193. }
  194. void make_segments(){
  195.     int zx = xes.gind(n)+1, zy = yes.gind(m)+1;
  196.  
  197.     for(s = 1; s<=max(zx, zy); s*=2);
  198.    
  199.     for(const auto& e : points){
  200.         bl_x[e.ff].insert(e.ss);
  201.         bl_y[e.ss].insert(e.ff);
  202.     }
  203.     for(int i = 0; i<=zy; i++){
  204.         bl_y[i].insert(0);
  205.         bl_y[i].insert(zx);
  206.     }
  207.  
  208.     for(int i = 0; i<=zx; i++){
  209.         bl_x[i].insert(0);
  210.         bl_x[i].insert(zy);
  211.     }
  212.    
  213.     for(const auto& e : points){
  214.         int x = e.ff, y = e.ss;
  215.         for(int i = 0; i<4; i++){
  216.             if(i >= 2){
  217.                 int dy = y + dcol[i], dx = x + drow[i];
  218.                 segment a = make(dx, dy, 0);
  219.                 if(a.l <= a.r && dy > 0 && dy < zy && dx > 0 && dx < zx){
  220.                     seg[sind++] = a;
  221.                 }              
  222.             }
  223.             else{
  224.                 int dx = x + drow[i], dy = y + dcol[i];
  225.                 segment a = make(dx, dy, 1);
  226.                 if(a.l <= a.r && dy > 0 && dy < zy && dx > 0 && dx < zx){
  227.                     seg[sind++] = a;
  228.                 }
  229.             }
  230.         }
  231.     }
  232.     for(int i = 1; i<max(zx, zy); i++){
  233.         if(sz(bl_y[i]) == 2 && i < zy){
  234.             seg[sind++] = segment(0, i, 1, zx-1);
  235.         }
  236.         //paralell to y axis
  237.         if(sz(bl_x[i]) == 2 && i < zx){
  238.             seg[sind++] = segment(1, i, 1, zy-1);
  239.    
  240.         }
  241.     }
  242.     //cout << "resutls\n";
  243.     sort(seg+1, seg+sind);
  244.     sind = unique(seg+1, seg+sind) - (seg+1);
  245.     for(int i = 1; i<sind+1; i++) seg[i].ind = i;
  246.     IND = sind+1;
  247.     assert(sind <= K*8 +100 + (3*K + q + 1)*2);
  248. }
  249.  
  250. void sweep(){
  251.     int root = 0;
  252.     sort(seg+1, seg+1+sind, cmp);
  253.     for(int i = 1; i<sind+1; i++){
  254.         if(seg[i].dir == 1){
  255.             U(seg[i].pos, seg[i].ind, root, 0, s);
  256.         }else{
  257.             Q(seg[i].l, seg[i].r+1, seg[i].ind, root, 0, s);
  258.         }
  259.     }
  260.     sort(seg+1, seg+sind+1);
  261.     root= 0;
  262.     for(int i = 1; i<sind+1; i++){
  263.         if(seg[i].dir == 0){
  264.         U(seg[i].pos, seg[i].ind, root, 0, s);
  265.         }else{
  266.             Q(seg[i].l, seg[i].r+1, seg[i].ind, root, 0, s);
  267.         }
  268.     }
  269. }
  270.  
  271. void bfs(int src){
  272.     queue<int> zero, one;
  273.     int dis = 0;
  274.     memset(dist, 63, sizeof(dist));
  275.     vis.reset();
  276.     dist[src] = 0;
  277.     zero.push(src);
  278.     while(sz(one) || sz(zero)){
  279.         if(sz(zero) == 0){
  280.             swap(zero, one);
  281.         }
  282.         int u = zero.front(); zero.pop();
  283.         if(vis[u]) continue;
  284.         vis[u] = 1;
  285.         if(u <= sind && sz(adj[u])){
  286.             for(const auto& e : adj[u]){
  287.                 int v = e.first;
  288.                 if(dist[v] > dist[u] + e.second){
  289.                     dist[v] = dist[u] + e.second;
  290.                     if(e.second) one.push(v);
  291.                     else zero.push(v);
  292.                 }
  293.             }
  294.         }else{
  295.             int v = lc[u];
  296.             if(v > 0 && dist[v] > dist[u] && rc[u] != -1){
  297.                 dist[v] = dist[u];
  298.                 //one.push(v);
  299.                 zero.push(v);
  300.             }
  301.             v = rc[u];
  302.             if(v > 0 && dist[v] > dist[u] && rc[u] != -1){
  303.                 dist[v] = dist[u];
  304.                 zero.push(v);
  305.             }
  306.             if(rc[u] == -1){
  307.                 v = lc[u];
  308.                 if(v && dist[v] > dist[u]){
  309.                     dist[v] = dist[u];
  310.                     zero.push(v);
  311.                 }
  312.             }
  313.         }
  314.     }
  315. }
  316.  
  317. bool cmp2(const pair<int, int>& a, const pair<int, int>& b){
  318.     return (a.second == b.second) ? (a.first < b.first) : (a.second < b.second);
  319. }
  320.  
  321. int gsind(segment a){
  322.     auto it = lower_bound(seg+1, seg+1+sind, a);
  323.     return it - seg;
  324. }
  325.  
  326. void answer(){
  327.     memset(ans, 63, sizeof(ans));
  328.     segment spx = make(source.ff, source.ss, 0);
  329.     int ssx = gsind(spx);
  330.     bfs(ssx);
  331.     for(int i = 0; i<q; i++){
  332.         ans[i] = min(ans[i], dist[gsind(make(queries[i].ff, queries[i].ss, 0))]);
  333.         ans[i] = min(ans[i], dist[gsind(make(queries[i].ff, queries[i].ss, 1))]);
  334.     }  
  335.     segment spy = make(source.ff, source.ss, 1);
  336.     int ssy = gsind(spy);
  337.     bfs(ssy);
  338.     for(int i = 0; i<q; i++){
  339.         ans[i] = min(ans[i], dist[gsind(make(queries[i].ff, queries[i].ss, 0))]);
  340.         ans[i] = min(ans[i], dist[gsind(make(queries[i].ff, queries[i].ss, 1))]);
  341.     }  
  342.     for(int i = 0; i<q; i++){
  343.         if(ans[i] > 1e9) ans[i] = -1;
  344.     }
  345. }
  346.  
  347.  
  348. void solve(){
  349.     cin >> n >> m >> K >> q;
  350.     for(int i = 0; i<K; i++){
  351.         int a, b;
  352.         cin >> a >> b;
  353.         points.pb(mp(a, b));
  354.         xes.add(a); yes.add(b);
  355.         if(a < n) xes.add(a+1);
  356.         if(b < m) yes.add(b+1);
  357.     }
  358.     xes.add(n);
  359.     yes.add(m);
  360.     cin >> source.ff >> source.ss;
  361.     xes.add(source.ff);
  362.     yes.add(source.ss);
  363.     for(int i = 0; i<q; i++){
  364.         int a, b;
  365.         cin >> a >> b;
  366.         xes.add(a); yes.add(b);
  367.         queries.pb(mp(a, b));
  368.     }
  369.     xes.norm();
  370.     yes.norm();
  371.     for(int i = 0; i<K; i++){
  372.         points[i] = mp(xes.gind(points[i].ff), yes.gind(points[i].ss));
  373.     }
  374.     for(int i = 0; i<q; i++){
  375.         queries[i] = mp(xes.gind(queries[i].ff), yes.gind(queries[i].ss));
  376.     }
  377.     source = mp(xes.gind(source.ff), yes.gind(source.ss));
  378.     make_segments();
  379.     sweep();
  380.     for(int i = 0; i<SEG; i++){
  381.         sort(all(adj[i]), cmp2);
  382.     }
  383.     answer();
  384.     for(int i = 0; i<q; i++){
  385.         cout << ans[i] << "\n";
  386.     }
  387. }
  388.  
  389. int main(){
  390.   cin.tie(0) -> sync_with_stdio(0);
  391.  
  392.   int T = 1;
  393.   //cin >> T;
  394.   while(T--){
  395.         solve();
  396.   }
  397.   return 0;
  398. }
  399.  
  400.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement