Codeforces Round #650 (Div. 3)
阿新 • • 發佈:2020-06-28
打的 vp,花了 1h 30min 切了前 6 個,後來花了 20min 把最後一題也切掉了.
難度不大,但是想要進前 10 的話手速還是要快一點.
A - Short Substrings
觀察一下字串,然後發現相同的保留一個就行.
#include <bits/stdc++.h> #define N 1087 #define ll long long #define setIO(s) freopen(s".in","r",stdin) using namespace std; char str[N]; void solve() { scanf("%s",str+1); int n=strlen(str+1); printf("%c",str[1]); for(int i=2;i<=n-2;i+=2) { printf("%c",str[i]); } printf("%c\n",str[n]); } int main() { // setIO("input"); int T; scanf("%d",&T); while(T--) solve(); return 0; }
B - Even Array
判斷合不合法很簡單,然後最小步數顯然就是偶數/奇數不合法的位置個數.
#include <bits/stdc++.h> #define N 1008 #define ll long long #define setIO(s) freopen(s".in","r",stdin) using namespace std; int a[N],c0,c1,c2; void solve() { int n; scanf("%d",&n); c0=c1=c2=0; for(int i=0;i<n;++i) { scanf("%d",&a[i]); if(a[i]&1) ++c1; else ++c0; if((a[i]&1)!=(i&1)) { ++c2; } } if(c0!=(n+1)/2) printf("-1\n"); else printf("%d\n",c2/2); } int main() { // setIO("input"); int T; scanf("%d",&T); while(T--) solve(); return 0; }
C - Social Distance
可以用差分陣列維護 0 的連通塊.
連通塊內貪心去填 1 就行,也就是 $\frac{len}{(k+1)}+(len \% (k+1) != 0)$
#include <bits/stdc++.h> #define N 200009 #define ll long long #define setIO(s) freopen(s".in","r",stdin) using namespace std; char str[N]; int a[N]; void solve() { int n,k; scanf("%d%d",&n,&k); scanf("%s",str+1); for(int i=1;i<=n+3;++i) a[i]=0; for(int i=1;i<=n;++i) { if(str[i]=='1') { a[max(1,i-k)]++; a[min(i+k,n)+1]--; } } int pre0=0,mx=0; for(int i=1;i<=n;++i) { a[i]+=a[i-1]; if(!a[i]) ++pre0; else { mx+=pre0/(k+1); if(pre0%(k+1)) ++mx; pre0=0; } } mx+=pre0/(k+1); if(pre0%(k+1)) ++mx; printf("%d\n",mx); } int main() { // setIO("input"); int T; scanf("%d",&T); while(T--) solve(); return 0; }
D - Task On The Board
從大到小依次考慮,顯然最大的 b[i]=0,然後次大的 b[i]=該位置到所有最大的距離.
這樣可以判斷序列中元素的 rank,然後再貪心去填字母就行了.
#include <bits/stdc++.h> #define N 53 #define ll long long #define setIO(s) freopen(s".in","r",stdin) using namespace std; char str[N]; int n,m,a[N],RK[N],cnt[N],num[N],ou[N]; void solve() { memset(RK,0,sizeof(RK)); memset(cnt,0,sizeof(cnt)); memset(num,0,sizeof(num)); memset(ou,0,sizeof(ou)); scanf("%s",str+1); n=strlen(str+1); for(int i=1;i<=n;++i) ++num[str[i]-'a']; scanf("%d",&m); for(int i=1;i<=m;++i) scanf("%d",&a[i]); int bu=0; for(int i=1;;++i) { int flag=0; for(int j=1;j<=m;++j) { if(RK[j]) continue; int cur=0; for(int t=1;t<=m;++t) { if(RK[t]&&RK[t]<i) cur+=abs(t-j); } if(cur==a[j]) RK[j]=i,flag=1,++cnt[i]; } if(!flag) break; bu=i; } int c=1; for(int i=27;i>=0;--i) { if(num[i]>=cnt[c]) { ou[c]=i; ++c; } if(c>bu) break; } for(int i=1;i<=m;++i) { printf("%c",'a'+ou[RK[i]]); } printf("\n"); } int main() { // setIO("input"); int T; scanf("%d",&T); while(T--) solve(); return 0; }
E - Necklace Assembly
迴圈節為 $k$,意味著序列可以分成若干段,每段長度都為 k,且所有段相等.
由於每段長度固定,所以可以二分段數.
然後由於這裡的迴圈節可能非常大,所以不妨分解 k 的因數,然後對每個因數求一下答案,最後取 max.
#include <bits/stdc++.h> #define N 2008 #define ll long long #define setIO(s) freopen(s".in","r",stdin) using namespace std; int cnt[30],n,K; char S[N]; int check(int x,int cur) { int tmp=0; for(int i=0;i<27;++i) { tmp+=cnt[i]/x; } return tmp>=cur; } int cal(int p) { int l=1,r=n,ans=0; while(l<=r) { int mid=(l+r)>>1; if(check(mid,p)) ans=mid,l=mid+1; else r=mid-1; } return ans*p; } void solve() { memset(cnt,0,sizeof(cnt)); scanf("%d%d",&n,&K); scanf("%s",S+1); for(int i=1;i<=n;++i) ++cnt[S[i]-'a']; int ans=0; for(int i=1;i<=n;++i) { if(K%i==0) { ans=max(ans,cal(i)); } } printf("%d\n",ans); } int main() { // setIO("input"); int T; scanf("%d",&T); while(T--) solve(); return 0; }
F2 - Flying Sort (Hard Version)
不難發現留下的是值域連續的一段,然後將值域兩端分別扔到前後.
那麼問題就轉化成求極長值域連續的段數長度.
所有數互不相同顯然很好求.
對於出現數字相同的情況,不難發現構成一定是 零散 + 所有值嚴格取到 + 零散的形式.
即只有最小和最大值可以不都取完,中間的必須都取完.
這個直接用 DP 求就行.
要特判中間沒有嚴格取到的情況.
#include <bits/stdc++.h> #define N 1000009 #define ll long long #define setIO(s) freopen(s".in","r",stdin) using namespace std; int f[N],a[N],A[N],fst[N],lst[N],pos[N],num[N],Num[N]; void solve() { int n; scanf("%d",&n); for(int i=1;i<=n;++i) { scanf("%d",&a[i]); A[i]=a[i]; } sort(A+1,A+1+n); int m=unique(A+1,A+1+n)-A-1; for(int i=1;i<=n+233;++i) f[i]=pos[i]=fst[i]=lst[i]=num[i]=Num[i]=0; for(int i=1;i<=n;++i) a[i]=lower_bound(A+1,A+1+m,a[i])-A,++Num[a[i]]; for(int i=1;i<=n;++i) { if(!fst[a[i]]) fst[a[i]]=i; lst[a[i]]=i; } int mx=0; for(int i=1;i<=n;++i) { f[i]=1; if(fst[a[i]]==i) { if(lst[a[i]-1]<i) f[i]=max(f[i],f[lst[a[i]-1]]+1); f[i]=max(f[i],num[a[i]-1]+1); } else f[i]=max(f[i],f[pos[a[i]]]+1); ++num[a[i]]; pos[a[i]]=i; if(lst[a[i]]==i) mx=max(mx,f[i]+Num[a[i]+1]-num[a[i]+1]); mx=max(mx,num[a[i]]+Num[a[i]+1]-num[a[i]+1]); } printf("%d\n",n-mx); } int main() { // setIO("input"); int T; scanf("%d",&T); while(T--) solve(); return 0; }