Solution - Codeforces 1190C Tokitsukaze and Duel

rizynvu發表於2024-11-14

考慮到兩人對應的操作是相同的,於是可以從對稱的角度來思考。

考慮到在先手做出操作後,後手一個較為特殊的操作是不做任何影響,也就是重複先手的操作。
能夠發現如果對於後手這不能必勝,那麼他一定不會去產生影響,並又把這個局面留給先手,相當於是先後手的交換。
對於先手又是同樣的,因為兩人操作相同,對於他也是不必勝的,那麼他也會重複操作留給後手,那麼就平局了。

於是能夠知道的是,如果初始狀態就能必勝,那麼先手必勝。
否則如果無論先手怎樣操作,後手都能必勝的話,後手必勝。
否則就是先手存在一種方式,使得操作後後手不能必勝,那麼兩人就會一直重複第一次的操作,最終平局。

對於判斷,可以提前預處理好字首同色段的長度與字尾連續段的長度。

那麼對於先手,其選擇了段 \([l, r]\),那麼他就只關心 \([1, l], [r, n]\) 是否同色。
對於後手,先手選擇了段 \([l, r]\) 塗成了顏色 \(c\),那麼只有當 \([1, l], [r, n]\) 只有一邊需要重新塗色且最遠顏色距離 \(\le k\) 即可。

時間複雜度 \(\mathcal{O}(n)\)

#include<bits/stdc++.h>
constexpr int maxn = 1e5 + 10;
int n, k;
char s[maxn];
bool f[maxn], g[maxn];
int fmn[maxn][2], fmx[maxn][2], gmn[maxn][2], gmx[maxn][2];
int main() {
   scanf("%d%d%s", &n, &k, s + 1);
   f[0] = true;
   for (int i = 1; i <= n; i++) {
      f[i] = f[i - 1] && (s[i] == s[1]);
   }
   g[n + 1] = true;
   for (int i = n; i; i--) {
      g[i] = g[i + 1] && (s[i] == s[n]);
   }
   if (f[n - k] || g[k + 1]) {
      return puts("tokitsukaze"), 0;
   }
   for (int l = 1, r = k; r <= n; l++, r++) {
      if (f[l - 1] && g[r + 1] && s[1] == s[n]) {
         return puts("tokitsukaze"), 0;
      }
   }
   fmn[0][0] = fmn[0][1] = n + 1;
   for (int i = 1; i <= n; i++) {
      for (int op : {0, 1}) {
         fmn[i][op] = fmn[i - 1][op], fmx[i][op] = fmx[i - 1][op];
      }
      fmn[i][s[i] - '0'] = std::max(fmn[i][s[i] - '0'], i);
      fmx[i][s[i] - '0'] = i;
   }
   gmx[n + 1][0] = gmx[n + 1][1] = 0;
   for (int i = n; i; i--) {
      for (int op : {0, 1}) {
         gmn[i][op] = fmn[i + 1][op], gmx[i][op] = gmx[i + 1][op];
      }
      gmx[i][s[i] - '0'] = std::max(gmx[i][s[i] - '0'], i);
      gmn[i][s[i] - '0'] = i;
   }
   bool fl = true;
   for (int l = 1, r = k; r <= n; l++, r++) {
      for (char c : {'0', '1'}) {
         bool gl = l > 1 && (! f[l - 1] || c != s[1]);
         bool gr = r < n && (! g[r + 1] || c != s[n]);
         if ((gl && gr) || (gl && fmx[l - 1][c ^ '1'] - fmn[l - 1][c ^ '1'] + 1 > k) || 
                           (gr && gmx[r + 1][c ^ '1'] - gmn[r + 1][c ^ '1'] + 1 > k)) {
            fl = false;
            break;
         }
      }
   }
   puts(fl ? "quailty" : "once again");
   return 0;
}

相關文章