太垃圾了,只做得来,前四题,比赛时打得更菜
A. Sushi for Two
本场比赛最良心的题
题意:给你一串1和2组成的数字,要求你求一个最大串的长度,这个最大串必须是1和2的数量相等,并且只能一边是1一边是2,既1和2不能交叉。做法直接把1和2 的数量压缩了,然后直接遍历找到最大值
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int a[N],n,ans;
int b[N];
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
ans=0;
memset(b,0,sizeof(b));
int cnt=1;
b[1]=1;
for(int i=2;i<=n;i++)
{
if(a[i]==a[i-1])
{
b[cnt]++;
}
else
{
//cout<<b[cnt]<<" ";
b[++cnt]=1;
}
}
//cout<<b[cnt]<<endl;
for(int i=2;i<=cnt;i++)
{
ans=max(ans,2*min(b[i],b[i-1]));
}
cout<<ans<<endl;
return 0;
}
B. Circus
这道题就不怎么良心了,但不过还是怪自己太菜。
题意,给你n个艺术家,有的艺术家可以表演小丑,有的可以表演杂技,有的都可以,有的什么都不可以,要求安排两场演出,每一场上的人数一样,并且第一场表演小丑的人数等于第二次表演杂技的人数。
比赛时以为是特定规律,结果怎么也过不了,后来发现其实是暴力,先把每一种艺术家的人数以及标号记录下来,然后枚举第一次出场的人数,如果枚举三种艺术家,由于最大加起来有5000会卡,但不过由于数据好像不强,把一个循环改成+=2或者+=4可以过,既然枚举三种不行那就枚举只能表演一种技艺的艺术家,然后把两种都可以的艺术家拿去平衡,如果不能就继续,不会随便拿来不位置就可以了。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int a,b,c,d,n;
char stra[N],strb[N];
int v[4][5010];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n;
cin>>stra>>strb;
a=b=c=d=0;
for(int i=0; i<n; i++)
{
if(stra[i]=='0'&&strb[i]=='0')
v[0][a++]=i+1;
else if(stra[i]=='1'&&strb[i]=='0')
v[1][b++]=i+1;
else if(stra[i]=='0'&&strb[i]=='1')
v[2][c++]=i+1;
else
v[3][d++]=i+1;
}
int flag=0;
for(int i=0; i<=b; i++)
{
if(i>n/2)
break;
for(int j=0; j<=c; j++)
{
if(i+j>n/2)
break;
int x=i,y=c-j;
int k=y+d-x;
if(k%2||k<0)
continue;
k=k/2;
if(k>d)
continue;
int t=n/2-i-j-k;
if(t<0||t>a)
continue;
int cnt=0;
for(int l=0; l<i; l++)
cout<<v[1][l]<<" ",cnt++;
for(int l=0; l<j; l++)
cout<<v[2][l]<<" ",cnt++;
for(int l=0; l<k; l++)
cout<<v[3][l]<<" ",cnt++;
for(int l=0; cnt<n/2; l++)
cout<<v[0][l]<<" ",cnt++;
flag=1;
if(flag)
break;
}
if(flag)
break;
}
if(!flag)
cout<<"-1";
cout<<endl;
return 0;
}
C. Skyscrapers
题意就和题上面说的差不多,简单说一下,就是给你一个n*m的数表,到第 i,j个数据,问第i行j列中,找出最小的一个x,使所有的值都在1到x之间,但不过i行j列单独的数据相对位置不变。
做法,吧每一行每一列的数据存储起来离散化,然后遍历数表,分别找到mp[i][j]在i行j列的相对大小,然后和i行j列离散后的数据个数一起处理得到答案,具体看代码。
其实我也说不清楚
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n,m,mp[1010][1010];
vector<int>l[1010],r[1010];
int ans[1010][1010];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>mp[i][j];
l[i].push_back(mp[i][j]);
r[j].push_back(mp[i][j]);
}
}
for(int i=1;i<=n;i++)
{
sort(l[i].begin(),l[i].end());
l[i].erase(unique(l[i].begin(),l[i].end()),l[i].end());
}
for(int j=1;j<=m;j++)
{
sort(r[j].begin(),r[j].end());
r[j].erase(unique(r[j].begin(),r[j].end()),r[j].end());
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
int t=mp[i][j],ml=l[i].size(),mr=r[j].size();
int llow=lower_bound(l[i].begin(),l[i].end(),t)-l[i].begin()+1;
int rlow=lower_bound(r[j].begin(),r[j].end(),t)-r[j].begin()+1;
if(llow>=rlow)
mr=llow-rlow+mr;
else
ml=rlow-llow+ml;
ans[i][j]=max(mr,ml);
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
cout<<ans[i][j]<<" ";
cout<<endl;
}
return 0;
}
D. Camp Schedule
就是一个kmp算法的应用
题意:给出两个01串 s和t 要求改变s中01的位置,使t串在s中出现次数最多,直接对t求一个next数组,然后统计s中01个数,依次填补,就得到答案,如果匹配一个t就跳next。
#include<bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10;
char a[N],b[N];
int nxt[N];
void getnxt(char s[])
{
nxt[0]=-1;
int i=0,j=-1;
int len=strlen(s);
while(i<len)
{
if(j==-1||s[i]==s[j])
{
i++,j++;
nxt[i]=j;
}
else
j=nxt[j];
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>a>>b;
getnxt(b);
int x=0,y=0;
int len=strlen(a);
for(int i=0;i<len;i++)
{
if(a[i]=='0')
x++;
else
y++;
}
string ans="";
int cnt=0;
len=strlen(b);
while(x>0&&y>0)
{
if(b[cnt]=='0'&&x>0)
x--,ans+='0';
if(b[cnt]=='1'&&y>0)
y--,ans+='1';
cnt++;
if(cnt==len)
cnt=nxt[cnt];
}
while(x--)ans+='0';
while(y--)ans+='1';
cout<<ans<<endl;
return 0;
}
后面的题做不来了。。。。。