Codeforces Round #517 Div. 1翻車記
阿新 • • 發佈:2018-10-31
A:真的懵逼了。冷靜了半天之後決定二分一下答案,然後先a安排上儘量小的再貪心地一個個擴大。40min才過。這個做法非常慫的以程式碼複雜度和時間複雜度為代價換取了比較穩的正確性,事實上由於1~n可以組合出1~n*(n+1)/2的所有數,只要從大到小貪心地放就可以了。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespaceView Codestd; 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) { intw=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。
#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; }View Code
然後就棄療了。
result:rank 227 rating +6 穩定的沒救了。