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
  • 相关阅读:
    Codeforces 177G2 Fibonacci Strings KMP 矩阵
    Codeforces Gym100187C Very Spacious Office 贪心 堆
    Codeforces 980F Cactus to Tree 仙人掌 Tarjan 树形dp 单调队列
    AtCoder SoundHound Inc. Programming Contest 2018 E + Graph (soundhound2018_summer_qual_e)
    BZOJ3622 已经没有什么好害怕的了 动态规划 容斥原理 组合数学
    NOIP2016提高组Day1T2 天天爱跑步 树链剖分 LCA 倍增 差分
    Codeforces 555C Case of Chocolate 其他
    NOIP2017提高组Day2T3 列队 洛谷P3960 线段树
    NOIP2017提高组Day2T2 宝藏 洛谷P3959 状压dp
    NOIP2017提高组Day1T3 逛公园 洛谷P3953 Tarjan 强连通缩点 SPFA 动态规划 最短路 拓扑序
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/13067694.html
Copyright © 2011-2022 走看看