zoukankan      html  css  js  c++  java
  • luogu P5112 FZOUTSY

    传送门

    毒瘤出题人,卡我常数

    如果后缀排序后将两两之间height(ge k)的后缀放在一组,那么每次询问的答案就是(sum_{i} inom{num[i]}{2})(num[i]是第i组后缀在[l,r]之间的后缀个数),这个就是小z的袜子.不过注意块大小要开成(frac{n}{sqrt{m}}),然后求sa[i]和height[i]可以建出后缀树然后贪心遍历整棵树得到

    莫队奇偶快排序比普通的慢

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    #define LL long long
    #define il inline
    #define re register
    #define db double
    
    using namespace std;
    const int N=3e6+10,M=1e5+10;
    il int rd()
    {
      int x=0,w=1;char ch=0;
      while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
      while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
      return x*w;
    }
    int n,m,kk,szz;
    int xzz[26]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,3,4,0,0,0,5,6},fa[N<<1],ch[N<<1][7],len[N<<1],id[N<<1],sa[N],tps,ls=1,tt=1;
    char cc[N];
    il void inst(char cc,int ii)
    {
      int np=++tt,p=ls;
      len[np]=len[p]+1,id[np]=ii,ls=np;
      while(p&&!ch[p][xzz[cc-'a']]) ch[p][xzz[cc-'a']]=np,p=fa[p];
      if(!p) fa[np]=1;
      else
        {
          int q=ch[p][xzz[cc-'a']];
          if(len[q]==len[p]+1) fa[np]=q;
          else
            {
              int nq=++tt;
              fa[nq]=fa[q],len[nq]=len[p]+1,fa[q]=fa[np]=nq;
              for(int i=0;i<7;++i) ch[nq][i]=ch[q][i];
              while(p&&ch[p][xzz[cc-'a']]==q) ch[p][xzz[cc-'a']]=nq,p=fa[p];
            }
        }
    }
    int to[N<<1],nt[N<<1],hd[N<<1],tot;
    il void add(int x,int y){++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot;}
    int ff[N<<1],he[N];
    il int findf(int x){return ff[x]==x?x:ff[x]=findf(ff[x]);}
    void dd(int x)
    {
      if(id[x]) ++tps,sa[tps]=id[x],he[tps]=len[findf(ls)],ls=x;
      for(int i=hd[x];i;i=nt[i]) dd(to[i]);
      ff[x]=fa[x];
    }
    int be[N],p,mm[N],nm[N];
    LL na,an[M];
    il void ad(int i){na+=nm[be[i]],++nm[be[i]];}
    il void dl(int i){--nm[be[i]],na-=nm[be[i]];}
    struct qu
    {
      int l,r,i;
      bool operator < (const qu &bb) const {return mm[l]!=mm[bb.l]?l<bb.l:/*((mm[l]&1)?r>bb.r:*/r<bb.r/*)*/;}
    }qq[M];
    
    int main()
    {
      n=rd(),m=rd(),kk=rd();
      szz=n/sqrt(m);
      scanf("%s",cc+1);
      for(int i=1;i<=n;++i) inst(cc[n-i+1],n-i+1);
      for(int i=1;i<=tt;++i) add(fa[i],i),ff[i]=i;
      ls=0,dd(1);
      for(int i=1;i<=n;++i) be[sa[i]]=p+=he[i]<kk,mm[i]=i/szz;
      for(int i=1;i<=m;++i) qq[i].l=rd(),qq[i].r=rd(),qq[i].i=i;
      sort(qq+1,qq+m+1);
      for(int i=1,l=1,r=0;i<=m;++i)
        {
          while(r<qq[i].r) ++r,ad(r);
          while(r>qq[i].r) dl(r),--r;
          while(l<qq[i].l) dl(l),++l;
          while(l>qq[i].l) --l,ad(l);
          an[qq[i].i]=na;
        }
      for(int i=1;i<=m;++i) printf("%lld
    ",an[i]);
      return 0; 
    }
    

    upd:这个代码里面的求sa和height是假的虽然能过

    到时再补

  • 相关阅读:
    Python简单的闹钟程序(Win)+开机自启
    (未完待续)学习机器学习必备的线性代数知识
    条件随机场 0 | 随机过程的概念及其统计特征
    Python-OpenCV学习(五):二维绘图
    Python-OpenCV学习(四):基本图像处理
    Python-OpenCV学习(二):OpenCV+python在windows上的安装
    CF 158A
    CF 84 div1 A
    CF 153 div1 A
    CF 171B
  • 原文地址:https://www.cnblogs.com/smyjr/p/10165764.html
Copyright © 2011-2022 走看看