zoukankan      html  css  js  c++  java
  • HDU 5371 Hotaru的问题

    题意:
    Hotaru Ichijou最近沉迷于数学问题。现在她正在玩N序列。
    让我们定义N序列,它由三部分组成并满足以下条件:
    1.第一部分与第三部分相同
    2.第一部分和第二部分是对称的
    例如,序列{2,3,4,4,3,2,2,3,4}是N序列,其中第一部分{2,3,4}与第三部分{2,3,4}相同,第一部分{2,3,4}和第二部分{4,3,2}是对称的。
    给你n个正整数,你的任务是找到最大的连续子序列,即N序列。
    题解:
    ①首先,肯定要用Manacher求出回文半径
    ②定义L[i]:以i为回文中心的最长回文串的最左端点
    定义R[i]:以i为回文中心的最长回文串的最右端点
    ③将问题转化一下,我们发现,其实它就是让求回文中心(i,j),满足:
    L[i]<=j<i<=R[j]
    ④可以用并查集维护
    ⑤初始时 prt[j] = j,
    ⑥可以发现如果j对i不可行(R[j]<i),那么对i+1也一定不可行,此时令prt[j] = prt[j+1]
    ⑦对于i,从 j = prt[L[i]]开始跳,注意路径压缩
    ⑧最后的答案为ans*3,是因为在过程中我们只维护了第二部分也就是i~j的长度

    #pragma GCC optimize (2)
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn=200000+10;
    int n,len,s[maxn],L[maxn],R[maxn],P[maxn];
    int f[maxn];
    int Find(int x){
            if(f[x]==x)return x;
            return f[x]=Find(f[x]);
    }
    void Init();
    void Manacher();
    signed main(){
            int t;scanf("%d",&t);
            for(int i=1;i<=t;i++){
                    printf("Case #%d: ",i);
                    Init();
            }
            return 0;
    }
    void Init(){
            scanf("%d",&len);
            for(int i=1;i<=len;i++)scanf("%d",&s[i]);
            Manacher();
            for(int i=1;i<=n;i++)f[i]=i;
            int ans=0,tmp=0;
            for(int i=1;i<=n;i+=2){
                    int j=Find(L[i]);
                    while(j<i && j>0){
                            if(i<=R[j]){
                                    tmp=(i-j+1)>>1;
                                    ans=max(ans,tmp);
                                    break;
                            }
                            else if(i>R[j])f[j]=Find(j+2);
                            j=Find(j+2);
                    }
            }
            printf("%d
    ",ans*3);
            //最后的答案为ans*3,是因为在过程中我们只维护了第二部分也就是i~j的长度
    }
    void Manacher(){
            memset(P,0,sizeof(P));
            n=len<<1|1;
            for(int i=n;i>=1;i--)
                    if(i&1)s[i]=-1;
                    else s[i]=s[i>>1];
            s[0]=-2;
            int id=0,mx=0;
            for(int i=1;i<=n;i++){
                    if(i<mx)P[i]=min(P[id*2-i],mx-i);
                    else P[i]=1;
                    while(s[i+P[i]]==s[i-P[i]])P[i]++;
                    if(i+P[i]>mx)mx=i+P[i],id=i;
                    L[i]=i-P[i]+1;
                    R[i]=i+P[i]-1;
            }
    }

     

  • 相关阅读:
    ggplot常见语法汇总查询
    共线性图 | Alluvial Diagrams | Parallel plot | Parallel Coordinates Plot
    绿色地狱
    deepnude | 福利
    文献阅读 | A single-cell molecular map of mouse gastrulation and early organogenesis
    Seurat V3.0
    文献阅读 | Molecular Architecture of the Mouse Nervous System
    《我的团长我的团》
    RNA剪接体 Spliceosome | 冷冻电镜 | 结构生物学
    文献阅读 | Resetting histone modifications during human parental-to-zygotic transition
  • 原文地址:https://www.cnblogs.com/holy-unicorn/p/9510605.html
Copyright © 2011-2022 走看看