• 一道题20


    $n leq 100000$的字符串,多次问一个区间有多少位置不同的回文串。

    先插空做一次manacher,得到每个字符往左右延伸的长度$f$数组。如ACAA变*A*C*A*A*,那么所有*的$f_k$实际对应的回文串数是$frac{f_k}{2}$(一定整除),否则是$frac{f_k+1}{2}$(一定整除)。算答案的时候把后者的+1提出来,假设询问原串的区间$l,r$,那就是询问新串的$L=2l-1,R=2r+1$,只要输出$frac{1}{2}(r-l+1+sum_{k=L}^{R}min{f_k,k-L,R-k})$即可。

    $sum$那坨东西从$frac{L+R}{2}$处劈开得到两边,左边是$min{f_k,k-L}$,可以分类把$min$去掉,即$min{f_k,k-L}=f_k,k-f_k geq L$,$min{f_k,k-L}=k-L,k-f_k<L$,变成了一个二维数点问题,为了方便直接主席树搞定;右边同理。

    这个式子很好想到,稍加分析就可以求得,因此见到陌生的式子不要虚,按套路一步步求就好了。

     1 //#include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 //#include<time.h>
     5 //#include<math.h>
     6 //#include<set>
     7 //#include<queue>
     8 //#include<bitset>
     9 //#include<vector>
    10 #include<algorithm>
    11 #include<stdlib.h>
    12 using namespace std;
    13 
    14 #define LL long long
    15 LL qread()
    16 {
    17     char c; LL s=0; int f=1; while ((c=getchar())<'0' || c>'9') (c=='-') && (f=-1);
    18     do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s*f;
    19 }
    20 
    21 //Pay attention to '-' , LL and double of qread!!!!
    22 
    23 int n,m;
    24 #define maxn 260011
    25 char s[maxn]; int f[maxn];
    26 int r1[maxn],r2[maxn];
    27 struct SMT
    28 {
    29     struct Node{int ls,rs; LL f,k,c;}a[maxn*20];
    30     int size,n;
    31     void clear(int N) {n=N; size=0;}
    32     LL sf,sk,sc; int v;
    33     void in(int &x,int y,int L,int R,int p,int f,int k)
    34     {
    35         x=++size; a[x].f=a[y].f+f; a[x].k=a[y].k+k; a[x].c=a[y].c+1;
    36         if (L==R) return;
    37         int mid=(L+R)>>1;
    38         if (p<=mid) in(a[x].ls,a[y].ls,L,mid,p,f,k),a[x].rs=a[y].rs;
    39         else in(a[x].rs,a[y].rs,mid+1,R,p,f,k),a[x].ls=a[y].ls;
    40     }
    41     void in(int &x,int y,int p,int f,int k) {in(x,y,1,n,p,f,k);}
    42     void Query(int x,int L,int R,int ql,int qr)
    43     {
    44         if (ql<=L && R<=qr) {sf+=a[x].f*v; sk+=a[x].k*v; sc+=a[x].c*v; return;}
    45         int mid=(L+R)>>1;
    46         if (ql<=mid) Query(a[x].ls,L,mid,ql,qr);
    47         if (qr>mid) Query(a[x].rs,mid+1,R,ql,qr);
    48     }
    49     void query(int x,int y,int l,int r) {sf=sk=sc=0; v=1; Query(y,1,n,l,r); v=-1; Query(x,1,n,l,r);}
    50 }
    51 t1,t2;
    52 
    53 struct Lisa {int id,v; bool operator < (const Lisa &b) const {return v<b.v;} }lisa1[maxn],lisa2[maxn];
    54 int id1[maxn],id2[maxn];
    55 
    56 int main()
    57 {
    58     n=qread(); m=qread(); scanf("%s",s+1);
    59     for (int i=n;i;i--) s[i<<1]=s[i]; n=(n<<1)^1;
    60     for (int i=1;i<=n;i+=2) s[i]='$';
    61     
    62     for (int i=1,id=0;i<=n;i++)
    63     {
    64         if (f[id]+id>=i) f[i]=min(f[id]+id-i,f[id+id-i]);
    65         while (i+f[i]+1<=n && i-f[i]-1>0 && s[i+f[i]+1]==s[i-f[i]-1]) f[i]++;
    66         if (i+f[i]>f[id]+id) id=i;
    67     }
    68     
    69     for (int i=1;i<=n;i++) lisa1[i]=(Lisa){i,i-f[i]},lisa2[i]=(Lisa){i,i+f[i]};
    70     sort(lisa1+1,lisa1+1+n); sort(lisa2+1,lisa2+1+n);
    71     for (int i=1;i<=n;i++) id1[lisa1[i].id]=i,id2[lisa2[i].id]=i;
    72     t1.clear(n); t2.clear(n);
    73     for (int i=1;i<=n;i++)
    74     t1.in(r1[i],r1[i-1],id1[i],f[i],i),t2.in(r2[i],r2[i-1],id2[i],f[i],i);
    75     
    76     int l,r;
    77     while (m--)
    78     {
    79         l=qread(); r=qread();
    80         LL ans=r-l+1;
    81         l=2*l-1; r=2*r+1;
    82         int mid=(l+r)>>1;
    83         int p=upper_bound(lisa1+1,lisa1+1+n,(Lisa){0,l})-lisa1-1;
    84         t1.query(r1[l-1],r1[mid],1,p);
    85         ans+=t1.sk-t1.sc*l;
    86         t1.query(r1[l-1],r1[mid],p+1,n);
    87         ans+=t1.sf;
    88         p=upper_bound(lisa2+1,lisa2+1+n,(Lisa){0,r})-lisa2-1;
    89         t2.query(r2[mid],r2[r],1,p);
    90         ans+=t2.sf;
    91         t2.query(r2[mid],r2[r],p+1,n);
    92         ans+=t2.sc*r-t2.sk;
    93         printf("%lld
    ",ans/2);
    94     }
    95     return 0;
    96 }
    View Code
  • 相关阅读:
    php与nginx配置,不能运行php程序
    奇葩php之数组
    奇葩之mysql
    for语法研究
    php short tag不显示排查
    奇葩之mysql【三】我只想获得一个自增Id,我容易吗我
    男女不同
    Restart explorer
    iOS面试贴士
    phpmyadmin万能登陆密码
  • 原文地址:https://www.cnblogs.com/Blue233333/p/9299883.html
Copyright © 2020-2023  润新知