2017北京国庆刷题Day6 morning
期望得分:100+100+20=220
实际得分:100+100+20=220
模拟栈
#include<cstdio> #include<cstring> using namespace std; #define N 10002 char s[N],st[N]; int top; int main() { freopen("kakutani.in","r",stdin); freopen("kakutani.out","w",stdout); int n,len,lt; scanf("%d",&n); while(n--) { scanf("%s",s); len=strlen(s); top=0; for(int i=0;i<len;i++) if(s[i]=='4' || s[i]=='7') continue; else if(s[i]!='3') st[++top]=s[i]; else { if(st[top]=='1') top--; else st[++top]='3'; } if(top) for(int i=1;i<=top;i++) putchar(st[i]); else putchar('0'); printf(" "); } }
枚举i为间隔K个录像的左端点,那么间隔录像为[i,i+k-1]
设第一段为[Sa,Ta],第二段为[Sb,Tb],Ma为min[Sa,Ta],Mb为min[Sb,Tb]
随着Sa的左移,Ma单调不增
随着Tb的右移,Mb单调不增
如果枚举Sa,则有以下式子: Ta-Sa+1+Tb-Sb+1>=B
即Tb>=B+Sa+Sb-Ta-2
因为Tb右移,Mb单调不增,所以Tb取等号最优
所以二分Sa的位置,用st表查询Ma,Mb
#include<cmath> #include<cstdio> #include<iostream> #include<algorithm> #define N 1000001 using namespace std; int st[N][21]; int p,n; int logg2[N]; void read(int &x) { x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } } void stpre() { p=log2(n); for(int j=1,k=2;j<=p;j++,k<<=1) for(int i=1;i+k-1<=n;i++) st[i][j]=min(st[i][j-1],st[i+(k>>1)][j-1]); for(int i=1;i<=n;i++) logg2[i]=log2(i); } int getmin(int s,int t) { p=logg2[t-s+1]; int len=1<<p; return min(st[s][p],st[t-len+1][p]); } int main() { freopen("dota.in","r",stdin); freopen("dota.out","w",stdout); int A,B,k; read(n); read(A); read(B); read(k); for(int i=1;i<=n;i++) read(st[i][0]); stpre(); int Sa,Sb,Ta,Tb,Ma,Mb,Mi; int ans=0; int l,r,mid,tmp; for(int i=A+1;i<=n-A-k+1;i++) { Ta=i-1; Sb=i+k; Tb=max(Sb+A-1,B+i-A+Sb-Ta-2); Ma=getmin(i-A,Ta); Mb=getmin(Sb,Tb); l=1; r=i-A; tmp=min(Ma,Mb); while(l<=r) { mid=l+r>>1; Tb=max(Sb+A-1,B+mid+Sb-Ta-2); Ma=getmin(mid,Ta); Mb=getmin(Sb,Tb); tmp=max(tmp,min(Ma,Mb)); if(Ma<Mb) l=mid+1; else if(Ma==Mb) break; else r=mid-1; } ans=max(ans,tmp); } printf("%d",ans); }