当前位置: 首页 > news >正文

Codeforces Round 1029 (Div. 3)

A. False Alarm

在这里插入图片描述
在这里插入图片描述

思路

求最左边关着的门和最右边关着的门,如果距离大于x则说明来不及

// Author: zengyz
// 2025-06-08 22:35#include <bits/stdc++.h>using namespace std;
using i64 = long long;void solve()
{int n, x;cin >> n >> x;vector<int> a(n + 1);for(int i=0;i<n;i++)cin>>a[i];int idx1 = -1;int idx2 = n + 10;for (int i = 0; i < n; i++){if (a[i] == 1){idx1 = i;break;}}for (int i = n - 1; i >= 0; i--){if (a[i] == 1){idx2 = i;break;}}int cnt=idx2-idx1+1;if(cnt>x){cout<<"NO"<<endl;}else cout<<"YES"<<endl;return;
}int main()
{ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);int _T = 1;cin >> _T;while (_T--){solve();}return 0;
}

B. Shrink

在这里插入图片描述
在这里插入图片描述

思路

观察发现先填最大的,然后从大到小依次填在右边和左边就可以满足
deque完美满足条件

// Author: zengyz
// 2025-06-08 22:45#include <bits/stdc++.h>using namespace std;
using i64 = long long;void solve()
{int n;cin >> n;deque<int> d;for (int i = n; i >= 1; i--){if (i % 2)d.push_back(i);elsed.push_front(i);}while (d.size()){cout << d.front() << " ";d.pop_front();}cout<<endl;return;
}int main()
{ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);int _T = 1;cin >> _T;while (_T--){solve();}return 0;
}

C. Cool Partition

在这里插入图片描述
在这里插入图片描述

找出一个数列中最多子段,要求当前子段必须包含上一个子段的所有元素

思路1

想到第一段只选一个一定是最优的,用vector维护每个元素出现的位置,用Set记录已经出现过的所有元素,每次查询出现过的所有元素的最远位置tmp,可以用vector的队头元素取最大值,注意要将vector中存储的小于tmp的元素位置都删掉,即

for (auto it = s.begin(); it != s.end(); it++)
{while (v[*it][0] <= tmp){if (v[*it].size() == 1){flag = false;break;}v[*it].erase(v[*it].begin());}
}
// Author: zengyz
// 2025-06-08 22:52#include <bits/stdc++.h>using namespace std;
using i64 = long long;
void solve()
{int n;cin >> n;vector<int> a(n + 1);vector<vector<int>> v(n + 1);for (int i = 1; i <= n; i++){cin >> a[i];v[a[i]].push_back(i);}bool flag = true;int count = 1, idx = 1;set<int> s;s.insert(a[1]);if (v[a[1]].size() == 1){cout << 1 << endl;return;}elsev[a[1]].erase(v[a[1]].begin());int tmp = idx;while (flag){for (auto it = s.begin(); it != s.end(); it++)tmp = max(tmp, v[*it][0]);for (int j = idx; j <= tmp; j++)s.insert(a[j]);idx = tmp;count++;for (auto it = s.begin(); it != s.end(); it++){while (v[*it][0] <= tmp){if (v[*it].size() == 1){flag = false;break;}v[*it].erase(v[*it].begin());}}}cout << count << endl;return;
}int main()
{ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);int _T = 1;cin >> _T;while (_T--){solve();}return 0;
}

思路2

用两个set维护,x代表上一段中出现的,y代表当前这一段出现的
在遍历时在x中删除当前元素,在y中添加当前元素
如果x删完了代表已经出现过上一段出现的所有元素,此时答案加一,并把y–即这一段出现过的所有元素赋给x进行下一段判定

// Author: zengyz
// 2025-06-08 22:52#include <bits/stdc++.h>using namespace std;
using i64 = long long;
void solve()
{int n;cin >> n;vector<int> a(n + 1);for (int i = 1; i <= n; i++){cin >> a[i];}bool flag = true;int count = 0, idx = 1;set<int> x, y;for (int i = 1; i <= n; i++){x.erase(a[i]);y.insert(a[i]);if (x.size() == 0){x = y;y.clear();count++;}}cout << count << endl;return;
}int main()
{ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);int _T = 1;cin >> _T;while (_T--){solve();}return 0;
}

D. Retaliation

在这里插入图片描述
在这里插入图片描述
一个数组,每次可进行两种操作,一种是每个元素都减i,一种是每个元素都减n-i+1
求是否存在仅通过任意次上述两种操作使得数组清零

思路1

用数学方法解决,针对a[1]和a[2]可以求解一元二次方程得到x,y
a [ 1 ] = x + n ∗ y a[1]=x+n*y a[1]=x+ny
a [ 2 ] = 2 ∗ x + ( n − 1 ) ∗ y a[2]=2*x+(n-1)*y a[2]=2x+(n1)y
用2*(1)-(2)得 y = 2 ∗ a [ 1 ] − a [ 2 ] ( n + 1 ) y=\frac{2*a[1]-a[2]}{(n+1)} y=(n+1)2a[1]a[2] x = a [ 1 ] − n ∗ y x=a[1]-n*y x=a[1]ny

注意x,y均不能小于0,且x,y必须为整数,然后对n>=3的所有元素带入x,y看是否满足条件,如果均满足则为yes

// Author: zengyz
// 2025-06-09 11:00#include <bits/stdc++.h>using namespace std;
using i64 = long long;void solve()
{int n;cin >> n;vector<int> a(n + 1);for (int i = 1; i <= n; i++)cin >> a[i];int a1 = a[1], a2 = a[2];int a12_a2 = a1 * 2 - a2;if (a12_a2 % (n + 1)){cout << "NO" << endl;return;}int y = a12_a2 / (n + 1);int x = a1 - n * y;if (x < 0 || y < 0){cout << "NO" << endl;return;}for (int i = 3; i <= n; i++){if (a[i] != x * i + (n - i + 1) * y){cout << "NO" << endl;return;}}cout << "YES" << endl;return;
}int main()
{ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);int _T = 1;cin >> _T;while (_T--){solve();}return 0;
}

思路2

因为一次1操作和2操作会让整个数组整体减去(n+1)
所以目标是如何将这个数组的所有元素都先减为(n+1)的倍数
又因为每次操作最左边和最右边的数减的差距为(n-1) :
( n − 1 + 1 ) − 1 = n − 1 (n-1+1)-1=n-1 n1+11=n1
所以我们可以根据两端的差距来决定进行多少次1或2操作
注意如果有余数则说明两端元素不可能通过操作让他们相等,直接输出NO
操作完后左右两端的元素值会相等
如果此时整个数组中
所有元素均为n+1的倍数且所有元素均相等(可被相同次数的1和2操作减为0)且大于等于0(合法)那么就满足条件

// Author: zengyz
// 2025-06-08 23:59#include <bits/stdc++.h>using namespace std;
using i64 = long long;void solve()
{int n;cin >> n;vector<int> a(n + 1);for (int i = 1; i <= n; i++)cin >> a[i];if (abs(a[n] - a[1]) % (n - 1)){cout << "NO" << endl;return;}int res = abs(a[n] - a[1]) / (n - 1);if (a[n] > a[1])for (int i = 1; i <= n; i++)a[i] -= res * i;elsefor (int i = 1; i <= n; i++)a[i] -= res * (n - i + 1);// 特判1if (a[1] < 0 || a[1] % (n + 1)){cout << "NO" << endl;return;}for (int i = 2; i <= n; i++){if (a[i] % (n + 1) || a[i] < 0 || a[i] != a[i - 1]){cout << "NO" << endl;return;}}cout << "YES" << endl;return;
}int main()
{ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);int _T = 1;cin >> _T;while (_T--){solve();}return 0;
}

相关文章:

  • QT 仿网易云项目
  • SQL-labs通关(23-38)
  • 自动化过程中,如何定位一闪而过的toast?
  • 精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
  • 什么是VR全景展示?VR全景展示的用途
  • SOC-ESP32S3部分:QA-关于唤醒词更改及配置操作步骤
  • IIC(I2C)通信隔离电路分享
  • SQL Server 手动收缩ldf文件
  • 记录:RK3588 PWM调试
  • 算法:模拟
  • 12.找到字符串中所有字母异位词
  • 镜像里切换为普通用户
  • JDK 17 序列化是怎么回事
  • 【c语言】安全完整性等级
  • 「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案
  • Qt Http Server模块功能及架构
  • window 显示驱动开发-如何查询视频处理功能(二)
  • UE5 文本框自动换行
  • linux驱动开发(3)-页面分配器
  • yaml读取写入常见错误 (‘cannot represent an object‘, 117)
  • 软件开发和编程的区别/电脑系统优化软件排行榜
  • 承德网站网站建设/英雄联盟韩国
  • 石家庄做网站推广/电商网站大全
  • 做外国网站用什么服务器/互联网营销方式有哪些
  • 做优化排名会不会影响网站速度/企业网站优化方案
  • 网站建设客户分析调查表/百度输入法免费下载