【GDOI模拟】妮厨的愤怒

Description

栋栋和标标都是厨力++的妮厨。俗话说“一机房不容二厨”,他们两个都加入了某OI( )交流♂( )群,在钦定老婆的时候出现了偏差,于是闹得不可开交。可是栋栋是群内的长者,斗权限标标斗不过他。
于是标标单方面找到了LL仲裁庭,还帮栋栋出了律师的钱,要求按基本法来判定。法官点点喝了口果汁,仔细审查了案子,说中央资瓷栋栋连任,这是最吼的;标标还naive ,不要总想着搞一个大新闻,像那个南海某岛国一样。
标标不服,要到新日暮里和栋栋进行男人间的决斗♂。栋栋接住了标标丢去的蕾姆,并提出了一个问题:
给定一个长度为n的字符串s,给出 q个询问,每次询问子串S[l..r] 的最长回文子串长度。字符串下标从0开始。
标标被难住了,被禁言的他决定向你求助。
(以下内容为无意义灌水,请要怒 本次比赛的神犇跳过。)
如果这是galgame,那么轮到你选选项的时候了!
A.不帮并获得本题 分
B.帮助并被栋栋禁言
C.宣称自己也是妮厨与他们两个决斗
哪来的C选项啊QwQ

Solution

一眼就看出来要用manachar。
然后,当然是二分啦。
询问[l,r],那么就在[l+mid-1,r-mid+1]中查找就好了。
一眼的水题。

Code

#include
#include
#include
#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fod(i,a,b) for(i=a;i>=b;i--)
using namespace std;
const int maxn=100007;
int i,j,k,l,t,n,m,ans,r,mid,w;
int p[maxn*2],id,limit;
char s[maxn*2],st[maxn*2];
int f[21],g[maxn*2][21],wei[maxn*2][21];
int calc(int x,int y){
    int i,j=0;
    fod(i,20,0)if(x+f[i]<=y)j=max(g[x][i],j),x+=f[i];
    j=max(g[x][0],j);
    return j;
}
int main(){
    scanf("%d",&n);
    scanf("%s",st+1);
    fo(i,1,n)s[i*2-1]='#',s[i*2]=st[i];
    s[2*n+1]='#';
    fo(i,1,2*n+1){
        if(limit>i)p[i]=min(limit-i,p[2*id-i]);
        else p[i]=1;
        while(i+p[i]<=2*n+1&&i-p[i]&&s[i-p[i]]==s[i+p[i]])++p[i];
        if(i+p[i]>limit){
            id=i;
            limit=i+p[i];
        }
    }
    fo(i,1,2*n+1)p[i]--;
    f[0]=1;
    fo(i,1,20)f[i]=f[i-1]*2;
    fo(i,1,2*n+1)g[i][0]=p[i],wei[i][0]=i;
    fo(j,1,20){
        fo(i,1,2*n+1){
            if(i+f[j-1]<=2*n+1)g[i][j]=max(g[i][j-1],g[i+f[j-1]][j-1]);
            else g[i][j]=g[i][j-1];
        }
    }
    for(scanf("%d",&m);m;m--){
        scanf("%d%d",&k,&t);k++,t++;
        l=1,r=t-k+1;ans=0;k=k*2,t=t*2;
        while(l1)/2;
            int o=calc(k+mid-1,t-mid+1);
            if(o1;
            else l=mid;
        }
        printf("%d\n",l);
    }
}

你可能感兴趣的:(字符串,manachar,省选,GDOI,二分)