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'; } }