zoukankan      html  css  js  c++  java
  • CF741E Arpa's abnormal DNA and Mehrdad's deep interest

    原题链接

    超毒瘤的一道题。

    先想想如何比较在(S)(i,j)前插入(T)组成的字符串的大小。不妨设(i<j),两个字符串为(S_1,S_2)

    首先(S_{0..i-1})(S_{j..n-1})是不用管了,因为它们在(S_1,S_2)里面位置不变。剩下来的就是(S_{l..r-1}),设其为(s)。我们现在要比较的就是(s+T)(T+s)。不妨设(|s|le|T|),则要比较的是(3)部分:(s)(T_{0..|s|-1})(T_{|s|..|T|-1})(T_{0..|T|-|s|-1})(T_{|T|-|s|..|T|-1})(s)。这珂以通过建立(S+T)的后缀数组来求。通过这个求出一个数组(p_i),代表当把(T)插入到(S)的第(i)个元素前时的字符串的字典序排名。

    接下来就处理询问的事情。

    遇到这种在询问里有取模的限制,通常都是根号分治。这题也珂以这样。设块长为(B)。以下默认rmq为常用的ST表。

    (k>B),则直接这个询问的范围所覆盖的连续区间不超过(dfrac{N}{B})个。这就珂以直接对于原(p)数组建立rmq,然后暴力查询即珂。这一部分时间复杂度为(O(dfrac{N^2}{B}+Nlog N))

    (kle B),则把询问离线。之后枚举模数mod,再枚举摸mod的余数r,对于所有的(imod mod=r)(i)建立rmq,然后枚举询问,若(xle rle y)则通过计算算出这个询问在rmq上的左右端点后查询更新答案。这一部分的时间复杂度为(O(BN(log N+1))=O(BNlog N))

    (B=N^{1-varphi})就能过(别问我为什么是这么奇怪的数字)。

    代码:

    // Code by H~$~C
    #include <bits/stdc++.h>
    using namespace std;
    #define epoch_time chrono::steady_clock::now().time_since_epoch().count()
    static mt19937 __gen(epoch_time);
    #define random_shuffle(begin, end) shuffle(begin, end, __gen)
    #define fi first
    #define se second
    #define x1 x1_19260817
    #define y1 y1_19260817
    #define j1 j1_19260817
    #define x0 x0_19260817
    #define y0 y0_19260817
    #define j0 j0_19260817
    #define left left_19260817
    #define right right_19260817
    #define rank rank_19260817
    using uint = unsigned int;
    using ll = long long;
    using ull = unsigned long long;
    using pii = pair<int, int>;
    constexpr int inf = 0x3f3f3f3f;
    constexpr ll lnf = 0x3f3f3f3f3f3f3f3f;
    
    static const int Maxn = 100005;
    static const int SQRT = 137;
    static const int LOG = 20;
    
    int n, m, q;
    int ans[Maxn];
    char s[Maxn << 1], t[Maxn];
    int p[Maxn], id[Maxn];
    struct Query {
      int l, r, k, x, y, id;
      Query() = default;
      inline void read() {
        scanf("%d%d%d%d%d", &l, &r, &k, &x, &y);
      }
    } qry[Maxn];
    
    namespace suffix_array {
      static const int Maxn = ::Maxn << 1;
      int sa[Maxn], rnk[Maxn], height[Maxn], s[Maxn];
      int wa[Maxn], wb[Maxn], wc[Maxn], wv[Maxn];
      int ST[Maxn][LOG], LOG2[Maxn];
      inline bool cmp_sa(int *y, int a, int b, int l) {
        return y[a] == y[b] && y[a + l] == y[b + l];
      }
      template<typename T>
      void build_SA(T *r, int n, int m) {
        register int i, j, p;
        int *x = wa, *y = wb, *t; ++n;
        for (i = 0; i < n; ++i) s[i] = r[i];
        for (i = 0; i < m; ++i) wc[i] = 0;
        for (i = 0; i < n; ++i) wc[x[i] = s[i]]++;
        for (i = 1; i < m; ++i) wc[i] += wc[i - 1];
        for (i = n; ~--i; ) sa[--wc[x[i]]] = i;
        for (p = 1, j = 1; p < n; j <<= 1, m = p) {
          for (p = 0, i = n - j; i < n; ++i) y[p++] = i;
          for (i = 0; i < n; ++i) if (sa[i] >= j) y[p++] = sa[i] - j;
          for (i = 0; i < n; ++i) wv[i] = x[y[i]];
          for (i = 0; i < m; ++i) wc[i] = 0;
          for (i = 0; i < n; ++i) wc[wv[i]]++;
          for (i = 1; i < m; ++i) wc[i] += wc[i - 1];
          for (i = n; ~--i; ) sa[--wc[wv[i]]] = y[i];
          for (t = x, x = y, y = t, p = 1, x[*sa] = 0, i = 1; i < n; ++i)
            x[sa[i]] = cmp_sa(y, sa[i], sa[i - 1], j) ? p - 1: p++;
        }
        for (i = 0; i < n; ++i) rnk[sa[i]] = i;
        for (i = p = 0; i < n; height[rnk[i++]] = p)
          for (p ? p-- : 0, j = sa[rnk[i] - 1]; s[i + p] == s[j + p]; p++);
        LOG2[0] = -1;
        for (int i = 1; i <= n; ++i)
          LOG2[i] = LOG2[i >> 1] + 1, ST[i][0] = height[i];
        for (int j = 1; j < LOG; ++j)
          for (int i = 1; i + (1 << j) - 1 <= n; ++i)
            ST[i][j] = min(ST[i][j - 1], ST[i + (1 << (j - 1))][j - 1]);
      }
      // sa[rank] = name, rnk[name] = rank
      // height[i] = lcp(suffix(sa[i - 1]), suffix(sa[i]))
      inline int query_ST(int l, int r) {
        int k = LOG2[r - l + 1];
        return min(ST[l][k], ST[r - (1 << k) + 1][k]);
      }
      inline int query_lcp(int l, int r) {
        if (l == r) return inf;
        l = rnk[l], r = rnk[r];
        if (l > r) swap(l, r);
        return query_ST(l + 1, r);
      }
      inline int cmp_substring(int l, int r, int len) {
        if (query_lcp(l, r) >= len) return 0;
        return rnk[l] < rnk[r] ? -1 : 1;
      }
      inline bool cmp_insert(int l, int r) {
        bool is_swapped = false;
        if (l > r) swap(l, r), is_swapped = true;
        int t;
        if (l + m <= r) {
          t = cmp_substring(n, l, m);
          if (t) return (t < 0) ^ is_swapped;
          t = cmp_substring(l, l + m, r - (l + m));
          if (t) return (t < 0) ^ is_swapped;
          t = cmp_substring(r - m, n, m);
          if (t) return (t < 0) ^ is_swapped;
        }
        else {
          t = cmp_substring(n, l, r - l);
          if (t) return (t < 0) ^ is_swapped;
          t = cmp_substring(n + r - l, n, l + m - r);
          if (t) return (t < 0) ^ is_swapped;
          t = cmp_substring(l, n + l + m - r, r - l);
          if (t) return (t < 0) ^ is_swapped;
        }
        return 1 ^ is_swapped;
      }
    }
    using suffix_array::build_SA;
    using suffix_array::cmp_insert;
    
    int ST[Maxn][LOG], LOG2[Maxn];
    template<typename Func>
    inline void build_ST(int len, Func exact_key) {
      LOG2[0] = -1;
      for (int i = 1; i <= len; ++i) LOG2[i] = LOG2[i >> 1] + 1;
      for (int i = 1; i <= len; ++i) ST[i][0] = exact_key(i);
      for (int j = 1; j < LOG; ++j)
        for (int i = 1; i + (1 << j) - 1 <= len; ++i)
          ST[i][j] = min(ST[i][j - 1], ST[i + (1 << (j - 1))][j - 1]);
    }
    inline int query_ST(int l, int r) {
      int k = LOG2[r - l + 1];
      return min(ST[l][k], ST[r - (1 << k) + 1][k]);
    }
    
    signed main() {
      scanf("%s%s%d", s, t, &q);
      n = strlen(s);
      m = strlen(t);
      strcpy(s + n, t);
      build_SA<char>(s, n + m, 128);
      for (int i = 0; i <= n; ++i) p[i] = i;
      sort(p, p + n + 1, cmp_insert);
      for (int i = 0; i <= n; ++i) id[p[i]] = i;
    //  for (int i = 0; i <= n; ++i)
    //    fprintf(stderr, "p[%d] = %d, id[%d] = %d
    ", i, p[i], i, id[i]);
      
      for (int i = 1; i <= q; ++i) ans[i] = inf;
      for (int i = 1; i <= q; ++i) qry[i].read(), qry[i].id = i;
      sort(qry + 1, qry + q + 1, [&](const Query &x, const Query &y)->bool{
        return x.k < y.k;
      });
      
      // solve k >= SQRT
      build_ST(n + 1, [&](int x){return id[x - 1];});
      for (int i = 1; i <= q; ++i) {
        if (qry[i].k < SQRT) continue;
        for (int j = 0; j * qry[i].k <= n; ++j) {
          int mn = max(j * qry[i].k + qry[i].x, qry[i].l) + 1;
          int mx = min(j * qry[i].k + qry[i].y, qry[i].r) + 1;
          if (mn > mx) continue;
          ans[qry[i].id] = min(ans[qry[i].id], query_ST(mn, mx));
        }
      }
      // solve k < SQRT
      for (int i = 1, j = 1; i < SQRT && j <= q; ++i) {
        if (i != qry[j].k) continue;
        int ed = j;
    //    fprintf(stderr, "i = %d
    ", i);
        while (ed <= q && qry[ed].k == i) ++ed;
        for (int module = 0; module < i; ++module) {
          int length = (n + 1) / i + (module <= n % i) + 1;
          build_ST(length, [&](int x){return id[(x - 1) * i + module];});
    //      for (int k = 1; k <= length; ++k)
    //        fprintf(stderr, "ST[%d] = %d
    ", k, ST[k][0]);
          for (int k = j; k < ed; ++k) {
            if (qry[k].x > module || qry[k].y < module) continue;
            int left = (qry[k].l - module + i - 1) / i + 1;
            int right = (qry[k].r - module + i) / i;
            if (left > right) continue;
            ans[qry[k].id] = min(ans[qry[k].id], query_ST(left, right));
    //        fprintf(stderr, "id = %d, left = %d, right = %d
    ", qry[k].id, left, right);
          }
        }
        j = ed;
      }
      
      for (int i = 1; i <= q; ++i)
        printf("%d%c", ans[i] == inf ? -1 : p[ans[i]], " 
    "[i == q]);
      return 0;
    }
    
    
  • 相关阅读:
    Asp.Net Core Web MVC 调用Grpc,采用依赖注入
    .Net Core框架下 Grpc四种处理方法
    信息系统项目管理师高频考点(第二章)
    系统集成项目管理工程师高频考点(第二章)
    .Net Core框架下实现Grpc客户端和服务端
    .Net Framework框架下实现Grpc客户端和服务端
    Asp.Net Core Mvc项目登录IdentityServer4验证无法跳转问题
    IdentityServer4(五)
    MVC项目登录IdentityServer4报错, The cookie '.AspNetCore.Correlation has set 'SameSite=None' and must also set 'Secure'
    IdentityServer4(二)
  • 原文地址:https://www.cnblogs.com/libra9z/p/12482695.html
Copyright © 2011-2022 走看看