Codeforces Round #652 (Div. 2) /cf1369
赛后总结:
代码一定要改干净,赛场上A了2道,但是B题看过了,虽然觉得可能还有bug,不够优化,就不管了,结果赛后重判,又T了,然后把代码的cout<<endl换成printf("\n"),就过了。
可见不要有那种做完就完事的粗糙行为方式。
当然B题,我的代码思路还是不够简洁,官方教程讲的分析很精彩细致。
B题
题意:有一串01字符,如果x[i]=‘1’,x[i+1]=‘0’,那么可以消去x[i]或x[i+1],问消除的最简洁结果是什么,最简洁意味着字符串最短且字典序最小。
官方题解
#include <iostream>
#include <string>
using namespace std;
/*
[a]0000+0+
*/
int main(){
int t;
cin >> t;
while(t--){
int n;
cin >> n;
string s;
cin >> s;
int sw = 1;
for(int i = 1; i < s.size(); i++){
if(s[i] < s[i-1])sw = 0;
}
if(sw){ //则这个字符串为000000111111或者纯1,或者纯0
cout << s << '\n';
continue;
}
string ans;
for(int i = 0; i < s.size(); i++){
if(s[i] == '1')break;
ans.push_back('0');//前缀0
}
ans.push_back('0');//中间段不纯粹,由于上述已经找到了1,那么中间的必然可以处理为1个0.
for(int i = s.size()-1; i >= 0; i--){
if(s[i] == '0')break;
ans.push_back('1'); //后缀1
}
cout << ans << '\n';
}
}
我的代码
我就是纯粹模拟,用倒序的去做,后面如果先找到了0,那么0前面的1都可以消除。
#include "bits/stdc++.h"
using namespace std;
const int maxn=2e5+10;
char ss[maxn],ans[maxn];
int main()
{
int cas,n;
scanf("%d",&cas);
while (cas--)
{
scanf("%d",&n);
scanf("%s",ss+1);
int pp=0;
ans[pp]='1';
for(int i=n;i>=1;--i)
{
if(ss[i]=='0')
{
int k=i;
while (k>0&&ss[k-1]=='0')--k;
int u=k;
while (u>0&&ss[u-1]=='1')--u;
if(u!=k){i=u;
if(ans[pp]=='1')ans[++pp]='0';
}
else ans[++pp]='0';
}
else if(ss[i]=='1'&&ans[pp]=='0')
{
while (i>0&&ss[i-1]=='1')--i;
}
else ans[++pp]='1';
ans[pp+1]='\0';
}
for(int i=pp;i>=1;--i)printf("%c",ans[i]);
printf("\n");
}
return 0;
}
C题
题意:
有n个数字,k个人, a i a_i ai表示数字大小, k i k_i ki表示第i个人要收到的数字个数,问最优分配的情况下,每个人收到的最大值和最小值的和是多少?
思路:
如果这个人只要求一件礼物,肯定把最大的数字给他。这时候,下文中的最大数字也就是排除了这个的这些的次最大数字。
由于最大数字和最小数字必然会出现在sum中,那么就把它先给 k i k_i ki最大的那个人,然后把剩余最小的数字,都塞到这个人中,如此循环往复,就ok了。
#include "bits/stdc++.h"
using namespace std;
const int maxn=2e5+10;
typedef long long ll ;
ll want[maxn],gift[maxn];
bool cmp1(ll &a,ll &b)
{
return a>b;
}
int main()
{
// freopen("E:\\project folds\\Clion\\hello\\cmake-build-debug\\in.text","r",stdin);
int cas,n;
scanf("%d",&cas);
while (cas--)
{
int n,m;
ll ans=0;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;++i)scanf("%lld",&gift[i]);
for(int i=1;i<=m;++i)scanf("%lld",&want[i]);
sort(gift+1,gift+n+1,cmp1);
sort(want+1,want+m+1);
int i=1;
while (i<=m&&want[i]==1){ans+=gift[i]*2;++i;}
if(i==(m+1))
{printf("%lld\n",ans);
continue;}
int last=n;//记录最小的gift
sort(want+i,want+m+1,cmp1);//把朋友按照想要礼物的个数从大到小排列
for(;i<=m;++i)
{
ans+=gift[i];
ans+=gift[last];
want[i]-=1;
while (want[i]>0){--last;--want[i];}
}
printf("%lld\n",ans);
}
return 0;
}