• BZOJ 2754 喵星球上的点名


    题意:

    太长了不说了直接撂这了

    https://www.lydsy.com/JudgeOnline/problem.php?id=2754

    Sol:

    如果(ac)自动机的话可以把(fail)树抽出来然后建虚树,有点难写。

    (SAM)的话问题转化完以后和(sa)是一样的....

    按照(sa)的习惯我们把名和姓还有问分别串起来,然后做(SA)

    第一问就是对于每个(Len)合法的区间有多少种颜色,同时排除问题串的颜色。

    离线左端点排序做出(nxt)维护下一个颜色出现的位置,(BIT)点修就好了。

    第二问就是每个点被多少区间覆盖

    实际上就是碰见左端点++,碰见右端点就消掉这个右端点所属询问的左端点的贡献

    要让区间左右端点分别都从小到大排个序,不然会有锅。

    原因是一位一位的扫要求单增。

    还有一个地方就是数组要开很大...不然会挂...

    #include<cctype>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    const int N = 4e5 + 7;
    const int lim = 4e5;
    typedef long long LL;
    inline int max(int a, int b){return a > b ? a : b;}
    inline int min(int a, int b){return a > b ? b : a;}
    int x[N*2], y[N*2], sa[N*2], rk[N*2], c[N*2];
    int m = lim, n; int het[N*2], qlog[N*2], st[N*2][23];
    //#define R register
    int ss[N*2];int totp;
    inline void getSA() {
      for (int i = 1; i <= m; i++) c[i] = 0;
      for (int i = 1; i <= n; i++) c[x[i] = ss[i]]++;
      for (int i = 1; i <= m; i++) c[i] += c[i - 1];
      for (int i = 1; i <= n; i++) sa[c[x[i]]--] = i;
      for (int siz = 1, p = 0; siz <= n; siz <<= 1, p = 0) {
        for (int i = n - siz + 1; i <= n; i++) y[++p] = i;
        for (int i = 1; i <= n; i++) if (sa[i] > siz) y[++p] = sa[i] - siz;
        for (int i = 1; i <= m; i++) c[i] = 0;
        for (int i = 1; i <= n; i++) c[x[y[i]]]++;
        for (int i = 1; i <= m; i++) c[i] += c[i - 1];
        for (int i = n; i >= 1; i--) sa[c[x[y[i]]]--] = y[i], y[i] = 0;
        std :: swap(x, y), x[sa[1]] = 1, p = 1;
        for (int i = 2; i <= n; i++) x[sa[i]] = 
          (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + siz] == y[sa[i - 1] + siz]) ? p : ++p;
        if (p == n) break; m = p;
      } int k = 0;
      memset(het, 0, sizeof(het));
      for (int i = 1; i <= n; i++) rk[sa[i]] = i;
      for (int i = 1; i <= n; i++) if (rk[i] != 1) {
        if (k) k--;
        int j = sa[rk[i] - 1];
        while(j + k <= n && i + k <= n && ss[i + k] == ss[j + k]) k++;
        het[rk[i]] = k;
      } qlog[1] = 0;
      memset(st, 0, sizeof(st));
      for (int i = 2; i <= lim; i++) qlog[i] = qlog[i / 2] + 1;
      for (int i = 1; i <= lim; i++) st[i][0] = het[i];
      int logw = qlog[n];
      for (int i = 1; i <= logw; i++) for (int j = 1; j + (1 << i) - 1 <= n; j++)
        st[j][i] = min(st[j][i - 1], st[j + (1 << (i - 1))][i - 1]);
      memset(c, 0, sizeof(c));
    }
    const int inf = 1e9 + 7;
    inline int query(int x, int y) { if (x > y) std :: swap(x, y);
      if(x == y) return inf; x += 1; int logw = qlog[y - x + 1], ans;
      ans = min(st[x][logw], st[y - (1 << logw) + 1][logw]); return ans;
    } 
    
    int sq;int totc, cntx;int fq, col[2*N];
    #define lbt(x) x & -x;
    #define upmax 3e5
    inline void Modify(int x, int k) {while (x <= upmax) c[x] += k, x += lbt(x);}
    inline int query(int x) {
      int res = 0; while (x > 0) res += c[x], x -= lbt(x); return res;
    }
    struct ask {int l, r, id, x, ans;}q[N*2];
    inline int cmp(ask a, ask b) {return a.l == b.l ? a.r < b.r : a.l < b.l;}
    inline int cmp2(ask a, ask b) {return a.id < b.id;}
    int upadd = 1e4 + 3; int qPos[N], qsum; int queryLen[2*N];
    struct ANS {int q1, q2;} ansq[N*2];
    void init(){
      scanf("%d%d", &n, &sq), totp = n;
      for (int i = 1; i <= n; i++) {
        int Len; scanf("%d", &Len), totc++;
        for (int j = 1; j <= Len; j++) 
          scanf("%d", &ss[++cntx]), col[cntx] = totc;
        ss[++cntx] = ++upadd, col[cntx] = 0;
        scanf("%d", &Len);//, fir[++fq] = cntx + 1;
        for (int j = 1; j <= Len; j++) 
          scanf("%d", &ss[++cntx]), col[cntx] = totc;
        ss[++cntx] = ++upadd, col[cntx] = 0;
      } 
      for (int i = 1; i <= sq; i++) {
        int Len; scanf("%d", &Len); qPos[i] = cntx + 1; queryLen[i] = Len;
        for (int j = 1; j <= Len; j++) scanf("%d", &ss[++cntx]), col[cntx] = 0;
        ss[++cntx] = ++upadd, col[cntx] = 0;
      }
    } int afc[N*2];
    void dye() {
      for (int i = 1; i <= cntx; i++) afc[i] = col[sa[i]];
    }
    inline int findL(int l, int r, int x, int req) {
      while (l < r) {
        int MID = (l + r) >> 1;
        if (query(MID, x) >= req) r = MID;
        else l = MID + 1;
      } return l;
    }
    inline int findR(int l, int r, int x, int req) {
      while (l < r) {
        int MID = (l + r + 1) >> 1;
        if (query(x, MID) >= req) l = MID;
        else r = MID - 1; 
      } return r;
    } int pre[N*2], nxt[N*2], b[N*2];
    void solve1() {
      for (int i = 1; i <= sq; i++) {
        int queryx = rk[qPos[i]];
        int l = findL(1, queryx, queryx, queryLen[i]);
        int r = findR(queryx, cntx, queryx, queryLen[i]);
        q[i].l = l, q[i].r = r, q[i].id = i;
      } std :: sort(q + 1, q + sq + 1, cmp);
      for (int i = 1; i <= n; i++) if(1) {
        nxt[pre[afc[i]]] = i;
        if (!pre[afc[i]] && afc[i] > 0) b[i] = 1;
        pre[afc[i]] = i;
      }
      for (int i = 1; i <= n; i++) if(b[i]) Modify(i, b[i]);
      for (int i = 1; i <= n; i++) if (!nxt[i]) nxt[i] = upmax + 1;
      q[0].l = 1;
      for (int i = 1; i <= sq; i++) {
        if (q[i - 1].l != q[i].l)
          for (int j = q[i - 1].l; j <= q[i].l - 1; j++)
            if(afc[j]) Modify(nxt[j], 1);
        q[i].ans = query(q[i].r) - query(q[i].l - 1);
      } std :: sort(q + 1, q + sq + 1, cmp2);
      for (int i = 1; i <= sq; i++) printf ("%d
    ", q[i].ans);
    } 
    #define clear(x) memset(x,0,sizeof(x))
    int ansc[N*2];
    struct rqq {int l, r, id;}rq[N*2];
    inline int cmp3(rqq a, rqq b) {return a.r == b.r ? a.l < b.l : a.r < b.r;}
    void solve2() {
      memset(pre, 0, sizeof(pre)), memset(c, 0, sizeof(c));
      std :: sort(q + 1, q + sq + 1, cmp);
      for (int i = 1; i <= sq; i++) 
        rq[i].l = q[i].l, rq[i].r = q[i].r, rq[i].id = q[i].id;
      std :: sort(rq + 1, rq + sq + 1, cmp3);
      for (int i = 1, j = 1, k = 1; i <= n; i++) {
        for ( ; q[j].l == i && j <= sq; j++) Modify(i, 1);
        if(afc[i]) ansc[afc[i]] += query(i) - query(pre[afc[i]]);
        for ( ; rq[k].r == i && k <= sq; k++) Modify(rq[k].l, -1);
        pre[afc[i]] = i;
      }
      for (int i = 1; i <= totp; i++) printf ("%d ", ansc[i]); puts("");
    }
    int main() {
      init(), n = cntx, getSA(), dye(), solve1(), solve2();
    return 0;
    }
    
  • 相关阅读:
    leetcode——202.快乐数
    leetcode——136. 只出现一次的数字
    leetcode——74.搜索二维矩阵
    leetcode——240.搜索二维矩阵
    leetcode——414.第三大的数
    020 迭代器模式
    019 模板模式
    018 中介者模式
    017 命令模式
    016 责任链模式
  • 原文地址:https://www.cnblogs.com/cjc030205/p/11638095.html
Copyright © 2020-2023  润新知