Codeforces Round 960 (Div. 2)

题目链接:Codeforces Round 960 (Div. 2)

总结:Awa 2,Bwa 2,C一直wa。很难评价的一场。感觉D < C

A. Submission Bait

fag:博弈论

Description:给定n个数,初始有一个变量mx,两个玩家。每一轮操作选一个大于等于mx的数ai,令ai=0,mx=ai。不能操作的人输,问先手玩家是否能赢。

Solution:我们先考虑直接选最大值的情况,如果有奇数个最大值,那么先手赢。

  • 考虑有偶数个最大值,怎么做?显然我们不能选最大值,考虑次大值有奇数个,那么先手赢。如果次大值也有偶数个,只能再往下考虑。
  • 那么从最大次开始判断,只有有一个值有奇数个,那么先手赢,否则后手赢。

Competing: 第一发,只考虑了最大值的奇偶性;第二发,考虑了最大值的奇偶性和剩下所有数之和的奇偶性。

void solve(){
cin >> n;
vector<int> a(n + 1);
for (int i = 0; i < n; i ++){
int x;
cin >> x;
a[x] ++;
}
for (int i = n; i; i --){
if (a[i] & 1){
cout << "Yes\n";
return;
}
}
cout << "No\n";
}

B. Array Craft

fag:构造

Description: 给定一个n, 一个x,y。其中x为最大前缀位置:就是令前缀和最大且下标最小的下标。y为最大位置:就是令后缀和最大且下标最大的下标。1<=y<x<=n。构造一个长度为n的数组,元素只能为11,满足上述条件。

Solution:先考虑x,我们令x之后的数为0,考虑y,我们令y之前的数为0。然后令[y,x]之间的数为1

  • 但是元素只能是11,因此我们需要用1,1,1,1,...构造出0。构造时x之后应该紧跟1y之前应该紧跟1

Competing:令[y,x]区间的数全为1,没考虑到这可能导致前缀和最大值为0

void solve(){
int x, y;
cin >> n >> x >> y;
vector<int> a(n + 1, 1);
for (int i = 1; i < y; i ++){
a[i] = -1;
}
for (int i = x + 1; i <= n; i ++)
a[i] = -1;
for (int i = y; i >= 0; i -= 2){
a[i] = 1;
}
for (int i = x; i <= n; i += 2)
a[i] = 1;
for (int i = 1; i <= n; i ++)
cout << a[i] << " \n"[i == n];
}

C. Mad MAD Sum

fag: 思维?

Description:定义MAD为数组中至少出现两次的最大值。没有则为0。给定一个长度为n的数组a

  • MAD([1,2,1])=1,MAD([2,2,2,3,3]=3),MAD([1,2,3,4])=0
  • 初始时,sum=0,每回合sum+=aib数组更新为当前a数组的MAD,然后将a数组更新为b数组。
2 3 1 1 2 2 3 4 4 5
0 0 0 1 2 2 3 3 4 4
0 0 0 0 0 2 2 3 3 4
0 0 0 0 0 0 2 3 3 4
1 3 2 1 1 2 3 3
0 0 0 1 1 2 3 3
0 0 0 0 1 1 1 3

Solution:多模拟几组样例可以发现MAD数组一定是连续递增的。

  • 我们可以观察到数组有右移的特征。
  • 但是当MAD数组中出现一个数字时,下一轮它就会消失。因为MAD需要它至少出现两次。
  • 因此我们第一轮得到一个MAD数组,然后再模拟一轮去掉单个数字,之后的每一轮都是向右移动一次。

Competing:只跑了一次就像得到答案,好像也是可以,但是比较麻烦。多模拟样例,注意特征,总结规律

void solve(){
cin >> n;
vector<int> a(n), b(n);
int ans = 0;
map<int, int> mp;
int mx = 0;
for (int i = 0; i < n; i ++){
cin >> a[i];
ans += a[i];
mp[a[i]] ++;
if (mp[a[i]] >= 2 && a[i] > mx){
mx = a[i];
}
b[i] = mx;
}
mp.clear();
mx = 0;
for (int i = 0; i < n; i ++){
ans += b[i];
mp[b[i]] ++;
if (mp[b[i]] >= 2 && b[i] > mx)
mx = b[i];
a[i] = mx;
}
for (int i = 0; i < n; i ++)
ans += a[i] * (n - i);
cout << ans << endl;
}

D. Grid Puzzle

fag:思维

Description:有长度为n的数组,其中ai表示第i行,从[1,ai]都是黑色,其余是白色。有nn的棋盘。

  • 每次操作可以将一行染白,或者选一个22的矩阵染白。
  • 求将棋盘染白的最少操作次数。

Solution:显然当ai很大时,我们会直接将一行染白。考虑何时使用操作二。

  • 如果我们在这一行使用操作二,只会影响到下一行。
  • 每一行我们最大执行一次操作二,否则不如使用操作一。
  • 如果ai<=2,显然我们应该使用操作二,因为可以影响下一行。
  • 假设当前行被上一行影响了,如果前两个格子被染白,并且ai<=2那么不需要执行操作;如果ai<=4,如果前两个格子被(上一行)染白,我们需要使用操作二染白后两个格子。如果后两个格子被(上一行)染白,那么我们染白前两个格子;如果ai>4,我们使用操作一。
  • 根据以上分析,注意到我们需要记录每一行被上一个影响的前两个格子还是后两个格子。
/*
4
2 4 4 2
3
*/
void solve(){
cin >> n;
vector<int> a(n + 1);
vector<int> st(n + 1);
cnt ++;
int ans = 0;
for (int i = 0; i < n; i ++){
cin >> a[i];
if (a[i] == 0){
continue;
}
if (a[i] <= 2){
if (st[i] == 1)
continue;
else{
ans ++;
st[i + 1] = 1;
}
}
else if (a[i] <= 4){
if (st[i] == 1){
ans ++;
st[i + 1] = 2;
}
else if (st[i] == 2){
ans ++;
st[i + 1] = 1;
}
else
ans ++;
}
else{
ans ++;
}
}
cout << ans << endl;
}
posted @   Sakura17  阅读(28)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示