Codeforces 452F Permutation

rizynvu發表於2024-05-03

對於 \(a, b, \frac{a + b}{2}\) 肯定是需要固定下一些變數來考慮的。

考慮固定下 \(c = \frac{a + b}{2}\),考慮 \(a, b\)
那麼這樣的 \(a, b\) 肯定滿足 \(a - c = b - c, a\not = b\),那麼以 \(c\) 為中心,\(a, b\) 就是對稱的。
\(s_i = 0, 1\) 來表示 \(i\) 是在 \(c\) 的左邊或是右邊。
無解就是對於每個 \(c\),每組關於 \(c\) 對稱的 \(a, b\) 都滿足 \(s_a = s_b\)

這個條件轉化一下就是令邊界的關於 \(c\) 對稱的對為 \(x, y(x = 1\lor y = n)\)\(s_{x\sim y}\) 為迴文串。

那麼就可以用線段樹維護 \(\text{Hash}\),從左往右掃過去的時候修改對應的 \(s_i\),然後查詢一下區間正反的 \(\text{Hash}\) 進行比較。

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

程式碼
#include<bits/stdc++.h>
using ull = unsigned long long;
using u128 = __uint128_t;
constexpr inline u128 qpow(u128 a, u128 b, ull p, u128 v = 1) {
   while (b) {
      b & 1 && ((v *= a) %= p);
      (a *= a) %= p, b >>= 1;
   }
   return v;
}
constexpr inline bool checkpr(ull p) {
   int a = __builtin_ctzll(p - 1);
   ull b = p - 1 >> a;
   for (ull v : {2, 325, 9375, 28178, 450775, 9780504, 1795265022}) {
      u128 x = qpow(v, b, p), y = 0;
      for (int c = 0; c < a; c++, x = y) {
         y = x * x % p;
         if (y == 1 && x != 1 && x != p - 1)
            return false;
      }
      if (x != 1)
         return false;
   }
   return true;
}
constexpr inline ull getpr(ull l, ull r) {
   ull x = 0;
   for (int v : __DATE__ __TIME__ __TIMESTAMP__) x ^= (x + v) << 13;
   while (true) {
      x ^= x << 13, x ^= x >> 7, x ^= x << 17;
      ull y = l + x % (r - l);
      if (checkpr(y)) return y;
   }
   return 0;
}
constexpr ull P = getpr((ull)1e3, (ull)1e5), mod = getpr((ull)1e6, (ull)1e7);
const int maxn = 3e5 + 10;
int n;
struct node_t {
   ull v, b;
   inline node_t(ull v_ = 0, ull b_ = 0) {
      v = v_, b = b_;
   }
   inline node_t operator + (const node_t &a) const {
      return node_t((v * a.b + a.v) % mod, (b * a.b) % mod);
   }
} tr[maxn * 4][2];
inline void pushup(int k) {
   tr[k][0] = tr[k << 1][0] + tr[k << 1 | 1][0];
   tr[k][1] = tr[k << 1 | 1][1] + tr[k << 1][1];
}
void upd(int x, int y, int k = 1, int l = 1, int r = n) {
   if (l == r)
      return tr[k][0] = tr[k][1] = node_t(y, P), void();
   int mid = (l + r) >> 1;
   x <= mid ? upd(x, y, k << 1, l, mid) : upd(x, y, k << 1 | 1, mid + 1, r);
   pushup(k);
}
node_t qry(int x, int y, int op, int k = 1, int l = 1, int r = n) {
   if (x <= l && r <= y) return tr[k][op];
   int mid = (l + r) >> 1;
   if (y <= mid) return qry(x, y, op, k << 1, l, mid);
   if (mid < x) return qry(x, y, op, k << 1 | 1, mid + 1, r);
   node_t L = qry(x, y, op, k << 1, l, mid), R = qry(x, y, op, k << 1 | 1, mid + 1, r);
   return ! op ? (L + R) : (R + L);
}
void build(int k = 1, int l = 1, int r = n) {
   if (l == r)
      return tr[k][0] = tr[k][1] = node_t(0, P), void();
   int mid = (l + r) >> 1;
   build(k << 1, l, mid), build(k << 1 | 1, mid + 1, r);
   pushup(k);
}
int a[maxn];
int main() {
   scanf("%d", &n);
   for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
   build();
   for (int i = 1; i <= n; i++) {
      int len = std::min(a[i] - 1, n - a[i]), l = a[i] - len, r = a[i] + len;
      if (qry(l, r, 0).v != qry(l, r, 1).v)
         return puts("YES"), 0;
      upd(a[i], 1);
   }
   return puts("NO"), 0;
}

相關文章