zoukankan      html  css  js  c++  java
  • [loj2479]制胡窜

    建立后缀自动机,并用预处理出right集合,考虑对于一个长度为$len$且$right=left{ r_{1},r_{2}, cdots ,r_{k} ight}(r_{1}<r_{2}<cdots<r_{k})$(设字符串下标从1开始),有多少种方案使得其不合法(再用$c(n,2)$减去下面的$ans$)
    这就意味着对于一个任意一个$r$,都有$r-len+1le i<r$或$r-len+1le j<r$,分类讨论:
    1.存在$r_{a}<r_{b}<r_{c}$,满足$r_{b}-len+1ge r_{a}$且$r_{c}-len+1ge r_{b}$,那么a,b和c无法同时满足两个,即无解
    2.满足$r_{k}-len+1<r_{1}$,那么令$s=r_{1}-(r_{k}-len+1)$,则$ans=C(s,2)+scdot (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}$($ble a+1$)(令a和b分别为最大和最小的a和b),令A和B分别表示最大可能的a和最小可能的b(必然有$Ble A+1$),计算方案数:
    $ans=sum_{a=1}^{A}sum_{b=B}^{k}[ble a+1]egin{pmatrix} egin{Bmatrix} r_{1}-(r_{A}-len+1) (a=A) \ r_{a+1}-r_{a} (a<A) end{Bmatrix}end{pmatrix} egin{pmatrix} egin{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$,这样就不需要$ble a+1$的判断了
    再调换枚举顺序,考虑$sum_{b=B}^{i+1}egin{pmatrix} egin{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}egin{pmatrix} egin{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
    ",C(n+1)-query(rt[find(a[r],r-l+1)],r-l+1));
    134     }
    135 }
    View Code
  • 相关阅读:
    CF1202F You Are Given Some Letters...
    CF1178E Archaeology
    PTA (Advanced Level) 1005 Spell It Right
    PTA (Advanced Level) 1004 Counting Leaves
    Qt5——从零开始的Hello World教程(Qt Creator)
    PTA (Advanced Level) 1003 Emergency
    PTA (Advanced Level) 1002 A+B for Polynomials
    HDU 1272 小希的迷宫
    FZU 2150 Fire Game
    HihoCoder
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/13067694.html
Copyright © 2011-2022 走看看