Codeforces Round #813 (Div. 2)
#include<bits/stdc++.h>
using namespace std;
const int maxn = 120;
int a[maxn];
void solve() {
int n,k;
cin >> n >> k;
int cnt = k;
for(int i = 1; i <= n; i ++) {
cin >> a[i];
if(i <= k && a[i] <= k) cnt --;
}
cout << cnt << "\n";
}
int main()
{
int t; cin >> t;
while(t --) {
solve();
}
return 0;
}
1712B - Woeful Permutation
题意:确定序列 P{p1, p2 ... pn}中 1-n 的排列顺序,使得 lcm(1,p1)+lcm(2,p2)+…+lcm(n,pn) 最大。 lcm:最小公倍数
#include<bits/stdc++.h>
using namespace std;
void solve() {
int n;
cin >> n;
stack<int> s;
if(n % 2 == 0) {
for(int i = n; i >= 1; i --) {
if(i % 2 == 0) s.push(i - 1);
else s.push(i + 1);
}
}
else {
for(int i = n; i > 1; i --) {
if(i % 2 == 0) s.push(i + 1);
else s.push(i - 1);
}
s.push(1);
}
while(!s.empty()) {
cout << s.top() << " ";
s.pop();
}
cout << "\n";
}
int main()
{
ios::sync_with_stdio(false); std::cin.tie(nullptr);
int t; cin >> t;
while(t --) {
solve();
}
return 0;
}
1712C - Sort Zero
题意:给定一个长度为 n 的序列,每次可以选定一个数字,将序列中的所有该数字变为 0 ,问最少需要操作多少次可以将序列变为不下降序列。
题解一:
对前面数字的修改(->0) 会影响后面的相同的数字,导致可能出现新的不合法情况;每次修改时对所有位置的该相同数字进行遍历,如果一开始就不合法,np --,即假设修改后合法了, 如果修改为0后不合法, np++, 增加不合法数。np是关键
#include<bits/stdc++.h>
using namespace std;
int n;
void solve() {
cin >> n;
vector<int> a(n + 1);
vector<vector<int>> pos(n + 1);
for (int i = 1; i <= n; i ++) {
cin >> a[i];
pos[a[i]].push_back(i);
}
int np = 0;//不合法
int res = 0;//操作数
for (int i = 1; i < n; i ++) {
if (a[i] > a[i + 1]) {
np ++;
}
}
for (int i = 1; i <= n && np > 0; i ++) {
if (a[i] > 0) {
res ++;
for (auto j : pos[a[i]]) {
if (j > 1 && a[j - 1] > a[j]) np --;
if (j < n && a[j] > a[j + 1]) np --;
a[j] = 0;
if (j > 1 && a[j - 1] > a[j]) np ++;
if (j < n && a[j] > a[j + 1]) np ++;
}
}
}
cout << res << "\n";
}
int main() {
int t;
cin >> t;
while (t --) {
solve();
}
return 0;
}
题解二:
一开始从前往后遍历,如果出现a[i] > a[i + 1]的情况,就把a[i]加入set,然后向前搜索(1),将a[j]插入set,一直到a[j] == 0(初始0)。这样做超时了,我们只需加一句优化,a[i] = 0,即可缩小循环范围,每次搜索到最近的初始为0或修改为0的位置即可。
感慨一句,set真的很好用,不重不漏,避免了很多思维漏洞问题。用vis数组写了一遍,出了各种各样的bug,找到了原因,但还是没能改出来。比如:找到不满足条件的a[i],在向前遍历前将vis[a[i]]修改为1,如果前面再遇到a[i]就有可能提前结束了搜索,导致res不全 ;如果不修改vis[a[i]],就会出现多次添加的情况。
上AC代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 50;
int a[maxn];
void solve() {
int n;
cin >> n;
set<int> s;
for (int i = 1; i <= n; i ++) {
cin >> a[i];
}
for (int i = 1; i < n; i ++) {
a[i] = s.find(a[i]) == s.end() ? a[i] : 0;
a[i + 1] = s.find(a[i + 1]) == s.end() ? a[i + 1] : 0;
if (a[i] > a[i + 1]) {
int j = i - 1;
while(a[j] > 0) {//只相邻还不够,前面的非零都要为0
s.insert(a[j]);
j --;
}
s.insert(a[i]);
a[i] = 0;//加了一个优化, AC了
}
}
cout << s.size() << "\n";
}
int main() {
int t;
cin >> t;
while (t --) {
solve();
}
return 0;
}
vis 数组 wa了
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 50;
int a[maxn];
int vis[maxn];
//WA
void solve() {
int n;
cin >> n;
map<int, int> mp;
int re = 0;
memset(vis, 0, sizeof(vis));
for (int i = 1; i <= n; i ++) {
cin >> a[i];
mp[a[i]] = i;
}
for (int i = 1; i < n; i ++) {
if(vis[a[i]]) a[i] = 0;
if(vis[a[i + 1]]) a[i + 1] = 0;
if (a[i] > a[i + 1]) {
vis[a[i]] = 1;
re ++;
int j = i - 1;
if(vis[a[j]]) a[j] = 0;
while(a[j] > 0) {//只相邻还不够,前面的非零都要为0
re ++;
vis[a[j]] = 1;
j --;
if(vis[a[j]]) a[j] = 0; //如遇到a[i],会中途断掉,但是如果不加这个判断,就会多次添加res,WA 模拟:1 2 4 4 0 2就会搜索不到
}
}
}
cout << re << "\n";
}
int main() {
int t;
cin >> t;
while (t --) {
solve();
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!