逐月晴月杯

A. 无限旅馆

题目描述

有一个序列 \(A=[1]\),有三种操作:

  • \(A\rightarrow [x,A_1,A_2,\dots,A_N]\)
  • \(A\rightarrow [x,A_1,x,A_2,\dots,x,A_N]\)
  • \(A_x\) 的1值或确定序列长度小于 \(x\)

思路

由于 2 操作至多进行 \(\log\) 次,所以我们可以这样求解:

  • 每次不断往前跳,如果是连续的 1 就一起跳过去。

空间复杂度 \(O(N\log N)\),时间复杂度 \(O(N\log N)\)

代码

#include<bits/stdc++.h>
using namespace std;

const int MAXN = 100001;

struct Node {
  int op, x;
}s[MAXN];

int q, len, f[MAXN], fa[18][MAXN], cnt[MAXN], fir[MAXN];

int Get(int i, int p) {
  if(!i) {
    return 1;
  }else if(s[i].op == 2) {
    return (p % 2 ? s[i].x : Get(f[i], p / 2));
  }else if(p > cnt[i]) {
    return Get(fir[i], p - cnt[i]);
  }else {
    for(int j = 17; j >= 0; --j) {
      if(((p - 1) >> j) & 1) {
        i = fa[j][i];
      }
    }
    return s[i].x;
  }
}

int main() {
  ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  cin >> q;
  len = 1;
  for(int i = 1, last = 0; i <= q; ++i) {
    cin >> s[i].op >> s[i].x;
    f[i] = last;
    if(s[i].op == 1) {
      len = min(int(1e9) + 1, len + 1);
      cnt[i] = 1;
      fir[i] = last;
      if(s[last].op == 1) {
        fa[0][i] = last;
        fir[i] = fir[last];
        cnt[i] += cnt[last];
        for(int j = 1; j <= 17; ++j) {
          fa[j][i] = fa[j - 1][fa[j - 1][i]];
        }
      }
      last = i;
    }else if(s[i].op == 2) {
      len = min(int(1e9) + 1, 2 * len);
      last = i;
    }else if(s[i].op == 3) {
      cout << (s[i].x > len ? -1 : Get(last, s[i].x)) << "\n";
    }
  }
  return 0;
}

D. 镜面迷宫

题目描述

有一个由斜着/横/竖的镜面组成的 \(N\times M\) 的迷宫,有 \(Q\) 次询问,每次询问从 \((x,y)\) 向上/下/左/右发射激光会在多少个不同的镜子上反射。

思路

可以发现,我们对迷宫建图,一定会组成一个由链/环组成的图。依次处理即可。

时空复杂度均为 \(O(NM)\)

代码

#include<bits/stdc++.h>
using namespace std;

const int MAXN = 1005, dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, -1, 1};

int n, m, q, nxt[4 * MAXN * MAXN], cnt[4 * MAXN * MAXN], in[4 * MAXN * MAXN], ans[4 * MAXN * MAXN];
bool vis[4 * MAXN * MAXN], flag[4 * MAXN * MAXN];
char c[MAXN][MAXN];

int id(int x, int y, int d) {
  return d * n * m + (x - 1) * m + y;
}

bool add(int x, bool f) {
  x -= (x > 3 * n * m ? 3 : (x > 2 * n * m ? 2 : (x > n * m ? 1 : 0))) * n * m;
  flag[x] = flag[x + n * m] = flag[x + 2 * n * m] = flag[x + 3 * n * m] = f;
  return 1;
}

int main() {
  ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  cin >> n >> m;
  for(int i = 1; i <= n; ++i) {
    for(int j = 1; j <= m; ++j) {
      cin >> c[i][j];
    }
  }
  for(int i = 1; i <= n; ++i) {
    for(int j = 1; j <= m; ++j) {
      for(int d : {0, 1, 2, 3}) {
        int x = i + dx[d], y = j + dy[d], nd;
        if(x >= 1 && x <= n && y >= 1 && y <= m) {
          if(c[x][y] == '-') {
            nd = (!d ? 1 : (d == 1 ? 0 : d));
          }else if(c[x][y] == '|') {
            nd = (d == 2 ? 3 : (d == 3 ? 2 : d));
          }else if(c[x][y] == '/') {
            nd = (!d ? 3 : (d == 1 ? 2 : (d == 2 ? 1 : 0)));
          }else if(c[x][y] == '\\') {
            nd = (!d ? 2 : (d == 1 ? 3 : (d == 2 ? 0 : 1)));
          }
          nxt[id(x, y, nd)] = id(i, j, d);
          in[id(i, j, d)]++;
          cnt[id(x, y, nd)] = (d != nd);
        }
      }
    }
  }
  for(int i = 1; i <= 4 * n * m; ++i) {
    if(!in[i]) {
      int u = i, res = 0;
      for(; u; ans[u] = res, vis[u] = 1, res += (cnt[u] && !flag[u]), (cnt[u] && add(u, 1)), u = nxt[u]) {
      }
      u = i;
      for(; u; add(u, 0), u = nxt[u]) {
      }
    }
  }
  for(int i = 1; i <= 4 * n * m; ++i) {
    if(!vis[i]) {
      int u = i, res = 0;
      for(; !vis[u]; res += (cnt[u] && !flag[u]), (cnt[u] && add(u, 1)), vis[u] = 1, u = nxt[u]) {
      }
      u = i;
      do {
        ans[u] = res;
        add(u, 0);
        u = nxt[u];
      }while(u != i);
    }
  }
  cin >> q;
  for(int i = 1, x, y, d; i <= q; ++i) {
    string s;
    cin >> x >> y >> s;
    d = (s == "above" ? 0 : (s == "below" ? 1 : (s == "left" ? 2 : 3)));
    cout << ans[id(x, y, d)] << "\n";
  }
  return 0;
}
posted @ 2024-10-24 20:21  Yaosicheng124  阅读(7)  评论(0编辑  收藏  举报