A:真的懵逼了。冷静了半天之后决定二分一下答案,然后先a安排上尽量小的再贪心地一个个扩大。40min才过。这个做法非常怂的以代码复杂度和时间复杂度为代价换取了比较稳的正确性,事实上由于1~n可以组合出1~n*(n+1)/2的所有数,只要从大到小贪心地放就可以了。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,a,b,ans,ansa[1000000],ansb[1000000],cnta,cntb; bool flag[1000000]; bool check(int k) { int w=a;cnta=cntb=0; for (int i=1;i<=k;i++) if (w>=i) ansa[++cnta]=i,w-=i; else break; ansa[cnta+1]=k+1; for (int i=cnta;i>=1;i--) { if (!w) break; while (w&&ansa[i]+1<ansa[i+1]) ansa[i]++,w--; } if (b>=1ll*k*(k+1)/2-(a-w)) return 1; else return 0; } int main() { #ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif a=read(),b=read(); n=sqrt((a+b)*2ll)+2; int l=0,r=n; while (l<=r) { int mid=l+r>>1; if (check(mid)) ans=mid,l=mid+1; else r=mid-1; } int w=a;cnta=cntb=0; for (int i=1;i<=ans;i++) if (w>=i) ansa[++cnta]=i,w-=i; else break; ansa[cnta+1]=ans+1; for (int i=cnta;i>=1;i--) { if (!w) break; while (w&&ansa[i]+1<ansa[i+1]) ansa[i]++,w--; } printf("%d\n",cnta); for (int i=1;i<=cnta;i++) printf("%d ",ansa[i]),flag[ansa[i]]=1; cout<<endl; printf("%d\n",ans-cnta); for (int i=1;i<=ans;i++) if (!flag[i]) printf("%d ",i); return 0; }
B:首先对于修改字母显然要找到一个离左上角尽量远的可以将这段路径都改为a的点。这样可能是斜的一排点。然后考虑怎么使字典序最小,类似bfs的每次考虑斜的一排点,如果他可以由一个可能在答案中的点走来并成为最优解就给他标记上,最后由终点倒序输出即可。花了50min。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define N 2010 int n,m,a[N][N],f[N][N],ans[N*2],cnt=0; bool flag[N][N]; int main() { #ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); #endif n=read(),m=read(); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) { char c=getchar(); while (c<'a'||c>'z') c=getchar(); a[i][j]=c-'a'+1; } for (int i=0;i<=n;i++) f[0][i]=f[i][0]=n*n; for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) if (i==1&&j==1) f[i][j]=a[i][j]!=1; else f[i][j]=min(f[i-1][j],f[i][j-1])+(a[i][j]!=1); int step=-1; for (int k=2*n-1;k>=0;k--) { for (int i=1;i<=n;i++) { int j=k-i+2; if (1<=j&&j<=n&&f[i][j]<=m) {step=k;flag[i][j]=1;} } if (step!=-1) break; } for (int i=1;i<=step+1;i++) putchar('a'); flag[0][1]=1; for (int k=step+1;k<=2*n-1;k++) { int c=27; for (int i=1;i<=n;i++) { int j=k-i+2; if (1<=j&&j<=n&&(flag[i-1][j]||flag[i][j-1])) c=min(c,a[i][j]); } for (int i=1;i<=n;i++) { int j=k-i+2; if (1<=j&&j<=n&&(flag[i-1][j]||flag[i][j-1])&&a[i][j]==c) flag[i][j]=1; } } /*for (int i=1;i<=n;i++) { for (int j=1;j<=n;j++) cout<<flag[i][j]<<' '; cout<<endl; }*/ int x=n,y=n; while (x-1+y-1>step) { ans[++cnt]=a[x][y]; if (flag[x-1][y]) x--; else y--; } for (int i=cnt;i>=1;i--) putchar(ans[i]+'a'-1); return 0; }
然后就弃疗了。
result:rank 227 rating +6 稳定的没救了。