• P5108 仰望半月的夜空


    传送门

    这是一个比较不正常的写法……估计应该没几个和我这样写的……

    我们考虑倒着做,也就是依次考虑长度为(n,n-1,...,1)时的答案。发现长度为(n)时只能选第一个位置,为(n-1)时要选(1,2)中较优的位置……

    然后大力猜想一发倒着的答案是否保证不降,然而样例一直接把脸给打得啪啪疼

    然而倒着的时候答案的确有一个性质。比方说长度为(len)的时候有(i<j)(i)(j)更优,那么(j)就永远不可能是最优答案了。因为长度不断减小的时候永远满足(i)开头的字典序比(j)小或者两个字典序相等但(i)在更左边

    于是就可以用单调栈了。每一次把新的可以作为答案的点加进去,然后判断(st[top-1])是否比(st[top])更优,不断弹出,最后把栈顶最为当前长度的答案即可

    然而现在的问题就是怎么判更优,毕竟要比较字典序。我太菜了不会写SAM和SA之类的(不过话说这两个能不能弄也不知道啊……)于是想了一个比较鬼畜的办法:用(hash+)二分判断两个串相等的长度,那么只要比较它们下一位的大小就好了

    //minamoto
    #include<bits/stdc++.h>
    #define R register
    #define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
    #define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    using namespace std;
    char buf[1<<21],*p1=buf,*p2=buf;
    inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
    int read(){
        R int res,f=1;R char ch;
        while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
        for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
        return res*f;
    }
    char sr[1<<21],z[20];int C=-1,Z=0;
    inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
    void print(R int x){
        if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
        while(z[++Z]=x%10+48,x/=10);
        while(sr[++C]=z[Z],--Z);sr[++C]=' ';
    }
    const int N=3e5+5;
    int a[N],b[N],st[N],ans[N];
    int n,top,op,m;char s[N];
    struct Hash{
        int Base,P,bin[N],sum[N];
        inline void init(R int base,R int p){
            P=p,Base=base,bin[0]=1;
            fp(i,1,n)bin[i]=1ll*bin[i-1]*Base%P;
            fp(i,1,n)sum[i]=(1ll*sum[i-1]*Base+a[i]+1)%P;
        }
        inline int gethash(R int l,R int r){return (sum[r]-1ll*sum[l-1]*bin[r-l+1]%P+P)%P;}
    }h1,h2;
    inline bool equal(int l,int r,int ql,int qr){
        return h1.gethash(l,r)==h1.gethash(ql,qr)&&h2.gethash(l,r)==h2.gethash(ql,qr);
    }
    bool check(int ql,int qr,int len){
        if(equal(ql,ql+len-1,qr,qr+len-1))return true;
        int l=1,r=len,ans=0,mid;
        while(l<=r){
            mid=(l+r)>>1;
            if(equal(ql,ql+mid-1,qr,qr+mid-1))l=mid+1,ans=mid;else r=mid-1;
        }return a[ql+ans]<=a[qr+ans];
    }
    int main(){
    //	freopen("testdata.in","r",stdin);
        scanf("%d%d",&op,&n);
        if(op==26){
            m=35,scanf("%s",s+1);fp(i,1,n)a[i]=s[i]-'a';
        }else{
            fp(i,1,n)a[i]=b[i]=read();sort(b+1,b+1+n),m=unique(b+1,b+1+n)-b-1;
            fp(i,1,n)a[i]=lower_bound(b+1,b+1+n,a[i])-b;
        }h1.init(233,1e9+7),h2.init(19260817,998244353);
        fp(i,1,n){
            st[++top]=i;while(top>1&&check(st[top-1],st[top],n-i+1))--top;
            ans[n-i+1]=st[top];
        }fp(i,1,n)print(ans[i]);return Ot(),0;
    }
    
  • 相关阅读:
    grpc stream剖析
    Pravega架构小结
    Flink之对时间的处理
    一张图说清楚Flink水印和Lateness
    Flink kuduSink开发
    Axsure动态面板下不同状态页面间的交互
    Axsure制作图片动态验证码
    透过用户思维谈程序员的进阶之路
    redis整合Spring之序列化对象与反序列化
    Java基础面试题
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/10138205.html
Copyright © 2020-2023  润新知