[loj2479]制胡窜
建立后缀自动机,并用预处理出right集合,考虑对于一个长度为$len$且$right=\left\{ r_{1},r_{2}, \cdots ,r_{k} \right\}(r_{1}<r_{2}<\cdots<r_{k})$(设字符串下标从1开始),有多少种方案使得其不合法(再用$c(n,2)$减去下面的$ans$)
这就意味着对于一个任意一个$r$,都有$r-len+1\le i<r$或$r-len+1\le j<r$,分类讨论:
1.存在$r_{a}<r_{b}<r_{c}$,满足$r_{b}-len+1\ge r_{a}$且$r_{c}-len+1\ge r_{b}$,那么a,b和c无法同时满足两个,即无解
2.满足$r_{k}-len+1<r_{1}$,那么令$s=r_{1}-(r_{k}-len+1)$,则$ans=C(s,2)+s\cdot (n-1-s)+\sum_{i=1}^{k-1}(r_{i+1}-r_{i})^{2}$
3.两种情况都不满足,必然有i隔断了$r1,r2,\cdots,r_{a}$,j隔断了$r_{b},r_{b+1},\cdots,r_{k}$($b\le a+1$)(令a和b分别为最大和最小的a和b),令A和B分别表示最大可能的a和最小可能的b(必然有$B\le A+1$),计算方案数:
$ans=\sum_{a=1}^{A}\sum_{b=B}^{k}[b\le a+1]\begin{pmatrix} \begin{Bmatrix} r_{1}-(r_{A}-len+1)\ (a=A) \\ r_{a+1}-r_{a}\ (a<A) \end{Bmatrix}\end{pmatrix} \begin{pmatrix} \begin{Bmatrix} r_{B}-(r_{k}-len+1)\ (b=B) \\ r_{b}-r_{b-1}\ (b>B)\end{Bmatrix}\end{pmatrix}$
然后a和b的枚举范围修改为$ans=\sum_{a=B-1}^{A}\sum_{b=B}^{a+1}\cdots$,这样就不需要$b\le a+1$的判断了
再调换枚举顺序,考虑$\sum_{b=B}^{i+1}\begin{pmatrix} \begin{Bmatrix} r_{B}-(r_{k}-len+1)\ (b=B) \\ r_{b}-r_{b-1}\ (b>B)\end{Bmatrix}\end{pmatrix})=r_{a+1}-r_{k}+len-1$
代入原式,得到$ans=\sum_{a=B-1}^{A}\begin{pmatrix} \begin{Bmatrix} r_{1}-(r_{A}-len+1)\ (a=A) \\ r_{a+1}-r_{a}\ (a<A)\end{Bmatrix}\end{pmatrix}(r_{a+1}-r_{k}+len-1)$
再对$a$分类讨论,即$ans=(r_{1}-(r_{A}-len+1))(r_{A+1}-r_{k}+len-1)+\sum_{a=B-1}^{A}(r_{a+1}-r_{a})(r_{a+1}-r_{k}+len-1)$
最后,我们相当于要在求right集合的时侯用线段树顺便维护:1.区间和;2.区间平方和;3.区间相邻两数乘积和;4.区间左右端点;5.区间中数的个数,然后就可以算出上面的式子了
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 200005 4 #define ll long long 5 #define L ls[k] 6 #define R rs[k] 7 #define mid (l+r>>1) 8 struct ji{ 9 int nex,to; 10 }edge[N<<1]; 11 struct node{ 12 int l,r; 13 ll mul,sum[3]; 14 }tr[N*20]; 15 int V,VV,E,las,n,m,l,r,a[N],mx[N],nex[N],head[N],rt[N],ls[N*20],rs[N*20],ch[N][11],f[N][21]; 16 char s[N]; 17 ll C(int n){ 18 return n*(n-1LL)/2; 19 } 20 ll sqr(int n){ 21 return 1LL*n*n; 22 } 23 node up(node x,node y){ 24 node k; 25 k.l=min(x.l,y.l); 26 k.r=min(x.r,y.r); 27 k.mul=x.mul+y.mul; 28 if (x.sum[0]*y.sum[0])x.mul+=1LL*x.r*y.l; 29 for(int i=0;i<3;i++)k.sum[i]=x.sum[i]+y.sum[i]; 30 return k; 31 } 32 void update(int &k,int l,int r,int x){ 33 if (!k)tr[k=++VV]=tr[0]; 34 if (l==r){ 35 tr[k].l=tr[k].r=tr[k].sum[1]=x; 36 tr[k].sum[0]=1; 37 tr[k].sum[2]=1LL*x*x; 38 return; 39 } 40 if (x<=mid)update(L,l,mid,x); 41 else update(R,mid+1,r,x); 42 tr[k]=up(tr[L],tr[R]); 43 } 44 int merge(int k1,int k2){ 45 if (k1*k2==0)return k1+k2; 46 int k=++VV; 47 L=merge(ls[k1],ls[k2]); 48 R=merge(rs[k1],rs[k2]); 49 tr[k]=up(tr[L],tr[R]); 50 return k; 51 } 52 int query1(int k,int l,int r,int x){//最后一个比x小 53 if (l==r)return l; 54 if (tr[R].l>=x)return query1(L,l,mid,x); 55 return query1(R,mid+1,r,x); 56 } 57 int query2(int k,int l,int r,int x){//第一个比x大 58 if (l==r)return l; 59 if (tr[l].r>x)return query2(L,l,mid,x); 60 return query2(R,mid+1,r,x); 61 } 62 node query(int k,int l,int r,int x,int y){ 63 if ((!k)||(l>y)||(x>r))return tr[0]; 64 if ((x<=l)&&(r<=y))return tr[k]; 65 return up(query(L,l,mid,x,y),query(R,mid+1,r,x,y)); 66 } 67 void add(int c){ 68 int p=las,np=las=++V; 69 mx[np]=mx[p]+1; 70 while ((p)&&(!ch[p][c])){ 71 ch[p][c]=np; 72 p=nex[p]; 73 } 74 if (!p)nex[np]=1; 75 else{ 76 int q=ch[p][c]; 77 if (mx[q]==mx[p]+1)nex[np]=q; 78 else{ 79 int nq=++V; 80 mx[nq]=mx[p]+1; 81 nex[nq]=nex[q]; 82 memcpy(ch[nq],ch[q],sizeof(ch[q])); 83 nex[q]=nex[np]=nq; 84 while ((p)&&(ch[p][c]==q)){ 85 ch[p][c]=nq; 86 p=nex[p]; 87 } 88 } 89 } 90 } 91 void add(int x,int y){ 92 edge[E].nex=head[x]; 93 edge[E].to=y; 94 head[x]=E++; 95 } 96 void dfs(int k,int fa){ 97 f[k][0]=fa; 98 for(int i=1;i<=20;i++)f[k][i]=f[f[k][i-1]][i-1]; 99 for(int i=head[k];i!=-1;i=edge[i].nex) 100 if (edge[i].to!=fa){ 101 dfs(edge[i].to,k); 102 rt[k]=merge(rt[k],rt[edge[i].to]); 103 } 104 } 105 int find(int k,int len){ 106 for(int i=20;i>=0;i--) 107 if (mx[f[k][i]]>=len)k=f[k][i]; 108 return k; 109 } 110 ll query(int k,int len){ 111 int a=query1(k,1,n,tr[k].l+len-1),b=query2(k,1,n,tr[k].r-len+1); 112 if (a+1<b)return 0; 113 if (tr[k].r-len+1<tr[k].l){ 114 int s=tr[k].l-(tr[k].r-len+1); 115 return C(s)+s*(n-1LL-s)+2*tr[k].sum[2]-2*tr[k].mul-sqr(tr[k].l)-sqr(tr[k].r); 116 } 117 int aa=query2(k,1,n,a),bb=query1(k,1,n,b); 118 return 1LL*(tr[k].l-(a-len+1))*(aa-tr[k].r+len-1)+(bb-aa)*(tr[k].r-len+1LL)+query(k,1,n,b,aa).sum[2]-query(k,1,n,bb,aa).mul; 119 } 120 int main(){ 121 scanf("%d%d%s",&n,&m,s); 122 V=las=1; 123 tr[0].l=n+1; 124 for(int i=0;i<n;i++){ 125 add(s[i]-'0'); 126 a[i+1]=las; 127 update(rt[las],1,n,i+1); 128 } 129 memset(head,-1,sizeof(head)); 130 for(int i=1;i<=V;i++)add(nex[i],i); 131 for(int i=1;i<=m;i++){ 132 scanf("%d%d",&l,&r); 133 printf("%lld\n",C(n+1)-query(rt[find(a[r],r-l+1)],r-l+1)); 134 } 135 }