Codeforces Round #634 Div. 3
比赛链接 https://codeforces.com/contest/1335
比赛记录 https://blog.csdn.net/cheng__yu_/article/details/105395197
A. Candies and Two Sisters(水)
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5,mod=1e9+7;
const int inf=0x3f3f3f3f;
int t,n;
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
int ans;
if(n&1)
ans=n/2;
else
ans=n/2-1;
printf("%d\n",ans);
}
return 0;
}
B. Construct the String(水)
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5,mod=1e9+7;
const int inf=0x3f3f3f3f;
int t,n,a,b;
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&a,&b);
string s="";
char x='a';
int cnt=0;
while(n--)
{
s+=x;
x++;
cnt++;
if(cnt==b)
cnt=0,x='a';
}
cout<<s<<"\n";
}
return 0;
}
C. Two Teams Composing
思路:set记录不同的数的个数a,map找出现次数最大的数b。ans就是min(a,b)。然后b如果比a多2的话,可以补充一个到a里面,ans+1即可
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5,mod=1e9+7;
const int inf=0x3f3f3f3f;
int t,n;
set<int> s;
map<int,int> m;
int main()
{
scanf("%d",&t);
while(t--)
{
s.clear(),m.clear();
scanf("%d",&n);
for(int i=1;i<=n;++i)
{
int x;
scanf("%d",&x);
s.insert(x);
m[x]++;
}
int maxx=0,cnt=0;
for(auto i : m)
{
if(i.second>cnt)
{
cnt=i.second;
maxx=i.first;
}
}
s.erase(maxx);
int x=s.size();
int ans;
if(x>cnt)
ans=2*cnt;
else
{
if(x+2<=cnt)
ans=(x+1)*2;
else
ans=x*2;
}
printf("%d\n",ans/2);
}
return 0;
}
D. Anti-Sudoku(思维)
思路:数独的每行、每列、每个
3
×
3
3\times3
3×3的格子都要有两个重复的数。
修改(1,1)(2,4)(3,7)(4,2)(5,5)(6,8)(7,3)(8,6)(9,9)就可以了
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5,mod=1e9+7;
const int inf=0x3f3f3f3f;
int t,n;
int a[10][10];
void solve(int i,int j)
{
if(a[i][j]==1)
a[i][j]=2;
else
a[i][j]=1;
}
int main()
{
scanf("%d",&t);
while(t--)
{
for(int i=1;i<=9;++i)
for(int j=1;j<=9;++j)
scanf("%1d",&a[i][j]);
solve(1,1);
solve(2,4);
solve(3,7);
solve(4,2);
solve(5,5);
solve(6,8);
solve(7,3);
solve(8,6);
solve(9,9);
for(int i=1;i<=9;++i)
{
for(int j=1;j<=9;++j)
printf("%d",a[i][j]);
puts("");
}
}
return 0;
}
E2. Three Blocks Palindrome (hard version)(枚举)
题意:找最长aba形块状回文
比赛体验:做题时就想到了 肯定是枚举每种数字。但最终还是没做出来,因为自己的做法,是先枚举数字a,然后找
a
a
a 左边出现的位置l,右边出现的位置r。然后统计
[
1
,
l
−
1
]
,
[
r
+
1
,
n
]
[1,l-1],[r+1,n]
[1,l−1],[r+1,n] 出现最多的数字,然后往中间缩。看似没什么问题,但是这种做法默认了枚举的数字要出现偶数次,显然就错误了。
思路:
- 先统计两边的,枚举每个数字第1个和最后1个,然后找中间出现最多的数字。
- 然后在枚举这个数字的第2个和倒数第2个,依次类推。
实现:把每个数字的位置存下来。然后对每个数字出现的次数做一个前缀和。这样可以 O ( 1 ) O(1) O(1) 获得 [ l , r ] [l,r] [l,r] 区间某个数字出现的次数
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=2e5+5,maxm=1e5+5;
const int mod=1e9+7,inf=0x7f7f7f7f;
int t,n;
int a[maxn];
vector<int> p[maxn];
int pref[210][maxn];
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=1;i<=200;++i)
for(int j=1;j<=n;++j)
pref[i][j]=0;
for(int i=1;i<=200;++i)
p[i].clear();
for(int i=1;i<=n;++i)
{
scanf("%d",&a[i]);
p[a[i]].push_back(i);
pref[a[i]][i]=1;
}
for(int i=1;i<=200;++i)
for(int j=1;j<=n;++j)
pref[i][j]+=pref[i][j-1];
int ans=0;
for(int i=1;i<=200;++i)
ans=max(ans,(int)p[i].size());
for(int i=1;i<=n;++i)
{
int cnt=pref[a[i]][i];
int l=p[a[i]][cnt-1]+1;
int x=p[a[i]].size();
if(x<cnt)
continue;
int r=p[a[i]][x-cnt]-1;
if(l>r)
continue;
for(int j=1;j<=200;++j)
ans=max(ans,pref[j][r]-pref[j][l-1]+2*cnt);
}
printf("%d\n",ans);
}
return 0;
}