zoukankan      html  css  js  c++  java
  • HDU 5785 Interesting

    求出(1,i-1)中与i构成回文的位置的和L[i],以及 i 与(i+1,n)中构成回文的位置和R[i]。

    然后枚举每一对L[i]*R[i+1],累加和就是答案。

    计算L[i]和R[i],可以利用manacher结果,o(n)处理得到。

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    const double pi=acos(-1.0),eps=1e-8;
    void File()
    {
        freopen("D:\in.txt","r",stdin);
        freopen("D:\out.txt","w",stdout);
    }
    inline int read()
    {
        char c = getchar();  while(!isdigit(c)) c = getchar();
        int x = 0;
        while(isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); }
        return x;
    }
    
    const int maxn=1000010;
    char str[maxn],tmp[maxn<<1];
    int Len[maxn<<1],n;
    LL outp[maxn],out[maxn];
    LL L[maxn],R[maxn];
    LL mod=1000000007;
    struct Seg { int l,r,zx; } seg[maxn<<1];
    int cnt;
    
    void init(char *st)
    {
        int len=strlen(st); tmp[0]='@';
        for(int i=1;i<=2*len;i+=2) tmp[i]='#',tmp[i+1]=st[i/2];
        tmp[2*len+1]='#', tmp[2*len+2]='$', tmp[2*len+3]=0;
    }
    
    void Manacher(char *st)
    {
        int mx=0,po=0,len=strlen(st);
        for(int i=1;i<=len;i++)
        {
            if(mx>i) Len[i]=min(mx-i,Len[2*po-i]);
            else Len[i]=1;
            while(st[i-Len[i]]==st[i+Len[i]]) Len[i]++;
            if(Len[i]+i>mx) mx=Len[i]+i, po=i;
        }
        Len[0]=1;
    }
    
    int main()
    {
       // File();
        while(~scanf("%s",str))
        {
    
            n=strlen(str);
            init(str); Manacher(tmp);
    
            memset(outp,0,sizeof outp); memset(out,0,sizeof out);
            int LEN=strlen(tmp);
    
            cnt=0;
            for(int i=1;i<LEN-1;i++)
            {
                if(tmp[i]=='#'&&Len[i]==1) continue;
                int l=i-Len[i]+1,r=i+Len[i]-1;
                if(tmp[l]=='#') l++,r--; l=l/2,r=r/2;
                seg[cnt].l=l, seg[cnt].r=r, seg[cnt].zx=(l+r+1)/2, cnt++;
            }
    
           LL sum=0,sz=0;int pos=0;
           for(int i=1;i<=n;i++)
           {
               while(pos<cnt&&seg[pos].zx<=i)
               {
                   sum=sum+seg[pos].l+seg[pos].r; sz++;
                   out[seg[pos].r]-=1; outp[seg[pos].r]-=(seg[pos].l+seg[pos].r); pos++;
               }
               L[i]=sum-sz*i;
               sum=sum+outp[i]; sz=sz+out[i];
           }
    
           for(int i=0;i<cnt;i++) seg[i].zx=(seg[i].l+seg[i].r)/2;
           memset(outp,0,sizeof outp); memset(out,0,sizeof out);
           sum=0,sz=0,pos=cnt-1;
    
           for(int i=n;i>=1;i--)
           {
               while(pos>=0&&seg[pos].zx>=i)
               {
                   sum=sum+seg[pos].l+seg[pos].r; sz++;
                   out[seg[pos].l]-=1; outp[seg[pos].l]-=(seg[pos].l+seg[pos].r); pos--;
               }
               R[i]=sum-sz*i;
               sum=sum+outp[i]; sz=sz+out[i];
           }
    
           LL ans=0;
           for(int i=1;i<=n-1;i++) ans=(ans+(L[i]%mod)*(R[i+1]%mod)%mod)%mod;
           printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    拦截导弹类问题 (Codevs4888零件分组POJ1065Wooden Sticks)(LIS及其覆盖问题)
    BZOJ1034[ZJOI2008]泡泡堂
    BZOJ1015[JSOI2008]星球大战starwar题解报告
    合唱队形(DP)
    美元和马克(dp)
    链式前向星
    hdu-6170(模拟)
    51nod-1117 聪明的木匠(优先队列)
    51nod-1095 Anigram单词(简单map)
    KingXMagicSpells 期望dp (记忆化搜索)
  • 原文地址:https://www.cnblogs.com/zufezzt/p/5734018.html
Copyright © 2011-2022 走看看