刷题记录和简单题解

bzoj4446 小凸玩密室

题解?不存在的

jzoj6457 基因进化
数据范围较小的情况:考虑相邻的2个可以反转的点,这2个点在当前有4种选择:

1.前面反转,后面不反转

2.前面不反转,后面不反转

3.前面不反转,后面反转

4.前面反转,后面反转

发现情况1,3中,实际上就是把原序列反转+前面最优序列,或者前面最优序列反转+原序列,所以不用考虑。

只需要考虑情况2,4,效果为把原序列反转+前面最优序列,或者前面最优序列反转+原序列

可以暴力判定,由于数据水可以拿满分。

正解要快速判定,可以哈希+二分。每次要使用一个数据结构,把当前这个串正序插入到前面最优答案串后,再逆序插到最优答案串前,用哈希+二分可以判断哪个更优。

这样子看似需要线段树多一个log,但是只要使用2个栈,栈维护前缀/后缀哈希值即可。

#include<bits/stdc++.h>
#define int long long
using namespace std;
#define N 600010
int t,a[N],n,m,b[N],p[N],vi[N];
struct hs{
    int c[N],d[N],c1,c2,bs,mo,mv[N],e[N],f[N];
    void pb(int x){
        c2++;
        f[c2]=x;
        d[c2]=(d[c2-1]*mv[c2-1]+x)%mo;
    }
    void pf(int x){
        c1++;
        e[c1]=x;
        c[c1]=(c[c1-1]*bs+x)%mo;
    }
    void cb(){c2--;}
    void cf(){c1--;}
    int q(int x,int y){
        if(x<=c1&&y<=c1)return (c[c1-x+1]-c[c1-y]*mv[y-x+1]%mo+mo)%mo;
        else if(x<=c1&&y>c1)return (c[c1-x+1]+d[y-c1]*mv[c1-x+1])%mo;
        else return (d[y-c1]-d[x-1-c1]*mv[y-x+1]%mo+mo)%mo;
    }
    int qp(int x){
        if(x<=c1)return e[c1-x+1];
        return f[x-c1];
    }
}x,y;
signed main(){
    freopen("reverse.in","r",stdin);
    freopen("reverse.out","w",stdout);
    cin>>t;
    x.bs=37;
    x.mo=998244353;
    x.mv[0]=y.mv[0]=1;
    for(int i=1;i<N;i++)
        x.mv[i]=x.mv[i-1]*37%998244353;
    y.bs=29;
    y.mo=1000000007;
    for(int i=1;i<N;i++)
        y.mv[i]=y.mv[i-1]*29%1000000007;
    while(t--){
        memset(vi,0,sizeof(vi));
        cin>>n>>m;
        for(int i=1;i<=n;i++)
            scanf("%lld",&a[i]);
        for(int i=1;i<=m;i++){
            int x;
            scanf("%lld",&x);
            vi[x]=1;
        }
        m=0;
        for(int i=1;i<=n;i++)
            if(!vi[i])b[++m]=i;
        if(!m){
            int ans=0;
            for(int i=1;i<=n;i++)
                ans=(ans+x.mv[i-1]*a[i])%998244353;
            printf("%lld\n",ans);
            continue;
        }
        x.c1=y.c1=x.c2=y.c2=0;
         for(int i=0;i<m;i++){
            if(!i){
                int v=1;
                for(int j=1;j<=b[i+1];j++){
                    if(a[j]<a[b[i+1]-j+1]){
                        v=1;
                        break;
                    }
                    else if(a[j]>a[b[i+1]-j+1]){
                        v=0;
                        break;
                    }
                }
                if(v){
                    for(int j=1;j<=b[i+1];j++){
                        x.pb(a[j]);
                        y.pb(a[j]);
                    }
                }
                else{
                    for(int j=b[i+1];j;j--){
                        x.pb(a[j]);
                        y.pb(a[j]);
                    }
                }
            }
            else{
                for(int j=b[i]+1;j<=b[i+1];j++){
                    x.pb(a[j]);
                    y.pb(a[j]);
                }
                for(int j=b[i]+1;j<=b[i+1];j++){
                    x.pf(a[j]);
                    y.pf(a[j]);
                }
                int l=1,r=b[i+1],ans=0;
                while(l<=r){
                    int md=(l+r)/2;
                    if(md==5){
                        md++;
                        md--;
                    }
                    if(x.q(1,md)==x.q(b[i+1]-b[i]+1,b[i+1]-b[i]+md)&&y.q(1,md)==y.q(b[i+1]-b[i]+1,b[i+1]-b[i]+md)){
                        l=md+1;
                        ans=md;
                    }
                    else r=md-1;
                }
                if(ans==b[i+1]||x.qp(ans+1)<x.qp(b[i+1]-b[i]+ans+1)){
                    for(int j=b[i]+1;j<=b[i+1];j++){
                        x.cb();
                        y.cb();
                    }
                }
                else{
                    for(int j=b[i]+1;j<=b[i+1];j++){
                        x.cf();
                        y.cf();
                    }
                }
            }
        }
        for(int i=b[m]+1;i<=n;i++)
            x.pb(a[i]);
        int r=0;
        for(int i=1;i<=n;i++)
            r=(r+x.qp(i)*x.mv[i-1])%998244353;
        cout<<r<<'\n'; 
    }
}
View Code

猜你喜欢

转载自www.cnblogs.com/cszmc2004/p/12603531.html
今日推荐