Codeforces Round #650 (Div. 3)
打的 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;
}

浙公网安备 33010602011771号