标签:顺序 space for div init hide mem isp 一段
t1
题意,用一个错误算法求逆序对,当前数为p[i]则daan+=max(0,i-p[i]);现在有n个数为1-n的排列,已经给出了前m个数,求有好多种排列方法使得该算法答案正确。
题解。
发现如果当前p[i]<=i则要求前面的所有内容都比他小,否则p[i]>i,则要求比他小的的内容全部在他前面,否则加少了。
设f[i][j]表示已经放完了前i个位置,最大的数是j的方案数。可知j>=i。
若j>=i则必能找到一个最小的值放进来f[i][j]+=f[i-1][j]。
考虑放一个大的值j,枚举比这个值小的k。f[i][j]+=f[i-1][k]。
先把已经给出的数预处理好在这样转移即可。
代码如下:
#include<bits/stdc++.h> using namespace std; const int N=205; const int mo=1e9+7; int T,a[N],f[N][N],n; bool book[N]; inline int read() { char c=getchar(); int x=0,f=1; while(!isdigit(c)) {if(c==‘-‘) f=-1;c=getchar();} while(isdigit(c)) {x=(x<<3)+(x<<1)+c-‘0‘;c=getchar();} return x*f; } int main() { T=read(); while(T--) { n=read();int m=read(); memset(a,0,sizeof(a)); memset(f,0,sizeof(f));f[0][0]=1; memset(book,0,sizeof(book)); int xiao=1; for(int i=1;i<=m;i++) a[i]=read(); for(int i=1;i<=n;i++) { if(a[i]) { for(int j=0;j<a[i];j++) f[i][a[i]]=(f[i][a[i]]+f[i-1][j])%mo; if(xiao==a[i]) for(int j=max(i,a[i]+1);j<=n;j++) f[i][j]=(f[i][j]+f[i-1][j])%mo; book[a[i]]=1; while(xiao<=n&&book[xiao]==1) xiao++; } else { for(int k=1;k<=n;k++) for(int j=0;j<k;j++) f[i][k]=(f[i][k]+f[i-1][j])%mo; for(int j=i;j<=n;j++) f[i][j]=(f[i][j]+f[i-1][j])%mo; } } cout<<f[n][n]<<"\n"; } }
t2
题意:给出一个字符串,将他的所有子串按字典序排列,q次询问每次询问新串的第k个字符是什么,强制在线。
题解:
使用后缀数组。
先求出height然后将每个后缀分割成几部分顺序加入新串,表示有这一段,重复了几次,从哪儿开头。
求出长度的前缀和然后二分查找出在哪一段,再二分查找出在这一段的哪里即可。
代码如下:
#include<bits/stdc++.h> #define int long long using namespace std; const int N=2e6+5; int sa[N],rk[N],n,x[N],y[N],height[N],tong[N],m=135; char c[N]; struct pigu { int l,r,cnt,pos; inline int tot() { return (l+r)*(r-l+1)/2*cnt; } inline int query(int cha) { int lq=l,rq=r,daan=l-1; while(lq<=rq) { int mid=(lq+rq)>>1; if(((1ll*(l+mid)*(mid-l+1))>>1)*cnt<cha) daan=mid,lq=mid+1; else rq=mid-1; } return pos+(cha-((1ll*(l+daan)*(daan-l+1))>>1)*cnt-1)%(daan+1); } }q[N]; inline int read() { char c=getchar(); int x=0,f=1; while(!isdigit(c)) {if(c==‘-‘) f=-1;c=getchar();} while(isdigit(c)) {x=(x<<3)+(x<<1)+c-‘0‘;c=getchar();} return x*f; } inline void get_sa() { for(int i=1;i<=n;i++) x[i]=c[i],tong[x[i]]++; for(int i=1;i<=m;i++) tong[i]+=tong[i-1]; for(int i=n;i>=1;i--) sa[tong[x[i]]--]=i; for(int k=1;k<=n;k<<=1) { int cnt=0; for(int i=n-k+1;i<=n;i++) y[++cnt]=i; for(int i=1;i<=n;i++) if(sa[i]>k) y[++cnt]=sa[i]-k; memset(tong,0,sizeof(tong)); for(int i=1;i<=n;i++) tong[x[i]]++; for(int i=1;i<=m;i++) tong[i]+=tong[i-1]; for(int i=n;i>=1;i--) sa[tong[x[y[i]]]--]=y[i]; memset(y,0,sizeof(y)); swap(x,y);cnt=0;x[sa[1]]=cnt=1; for(int i=2;i<=n;i++) { if(y[sa[i]]!=y[sa[i-1]]||y[sa[i]+k]!=y[sa[i-1]+k]) cnt++; x[sa[i]]=cnt; } if(cnt==n) break;m=cnt; } for(int i=1;i<=n;i++) rk[sa[i]]=i; int dao=0; for(int i=1;i<=n;i++) { if(rk[i]==1) continue; if(dao) dao--; int hu=sa[rk[i]-1]; while(c[i+dao]==c[hu+dao]) dao++; height[rk[i]]=dao; } } int pos[N],id[N],cnt1,sum[N]; inline void init() { int top=0;pos[0]=-1;id[0]=id[1]=n+1; for(int i=n;i>=1;i--) { int now=n-sa[i]+1; if(now==pos[top]) top--; while(height[i]<=pos[top]) { q[++cnt1]=(pigu){pos[top]+1,now,id[top]-i,sa[i]}; now=pos[top]; top--; } if(height[i]<now) q[++cnt1]=(pigu){height[i]+1,now,id[top]-i,sa[i]}; top++;pos[top]=height[i];id[top]=i; } for(int i=1;i<=cnt1/2;i++) swap(q[i],q[cnt1-i+1]); for(int i=1;i<=cnt1;i++) sum[i]=sum[i-1]+q[i].tot(); int Q=read(),su=0; while(Q--) { int a=read(),b=read(); a=(a*su)%b;a++; int now=lower_bound(sum+1,sum+cnt1+1,a)-sum; now=q[now].query(a-sum[now-1]); cout<<c[now]<<"\n"; su+=c[now]; } } signed main() { scanf("%s",c+1); n=strlen(c+1); get_sa(); init(); }
标签:顺序 space for div init hide mem isp 一段
原文地址:https://www.cnblogs.com/betablewaloot/p/12271440.html