第一次akdiv2,赛后ak怎么不算是ak呢

比赛链接cf908div2

A

这题是个骗人题,整个比赛会停下来就是一个人赢够了回合数,那么在谁这停下来就是谁赢了整个比赛,不用管每回合赢得规则。

#include<iostream>
using namespace std;
#include<string>
int main()
{
int t;
cin >> t; while (t--)
{
int n;
cin >> n;
string s;
cin >> s; int A = 0, B = 0;
for (int i = 0; i < s.size(); i++)
{
if (s[i] == 'A')
{
A++;
}
else
{
B++;
}
}
if (s[s.size() - 1] == 'A')cout << "A" << endl;
else cout << "B" << endl; }
return 0; }

B

先从最简单的情况考虑,或者说分析一下给的三个条件必须正好满足两个是什么意思

如果序列为一个数a重复三次,那么要满足任意两个条件,都不可避免的同时满足了三个条件

那么自然想到,要将两个条件分配给两个数,让他们分别去实现其中一个条件,比如,有两个5,两个6,那么就可以给两个5分别赋值为1,2,给两个6分别赋值为1 3

那么,我们可以先明确不满足的情况是这样的:出现次数大于等于2的数字小于两个。

而如果出现次数大于等于2的数字大于两个,我们就可以任意找两个数字,找到他们的两次出现位置,分别赋值为1,2,和1,3,然后其他所有位置都是1,就一定满足。

#include<iostream>
#include<unordered_map>
#include<queue>
using namespace std;
const int maxn = 100020;
#include<vector> int main()
{
int t;
cin >> t; while (t--)
{
int a[maxn] = { 0 };
int b[maxn] = { 0 }; int n;
cin >> n; unordered_map<int, int>mp; //记录每个数出现了多少次
int count_2 = 0; //记录有多少个数出现次数大于等于2
unordered_map<int, int>asdf;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
mp[a[i]]++; }
for (int i = 1; i <= n; i++)
{
if (mp[a[i]] >= 2&&asdf.count(a[i])==0)
{
count_2++; }
asdf[a[i]]++;
} if (count_2 < 2)
{
cout << -1 << endl;
}
else
{
int firstnum = -1, secondnum = -1;
int index = -1;
for (int i = 1; i <= n; i++)
{
if (mp[a[i]] >= 2)
{
firstnum = a[i];
index = i;
break;
}
}
for (int i = index + 1; i <= n; i++)
{
if (mp[a[i]] >= 2&&a[i]!=firstnum)
{
secondnum = a[i];
break;
}
} int countfirst = 0, countsecond = 0; for (int i = 1; i <= n; i++)
{
if (a[i] == firstnum)
{
countfirst++;
b[i] = countfirst;
if (countfirst == 2)
{
break;
}
}
}
for (int i = 1; i <= n; i++)
{
if (a[i] == secondnum)
{
countsecond++;
b[i] = countsecond;
if (countsecond == 2)
{
b[i] = 3;
break;
}
}
} for (int i = 1; i <= n; i++)
{
if (b[i] == 0)
{
b[i] = 1;
} }
for (int i = 1; i <= n; i++)
{
cout << b[i] << " "; }
cout << endl;
} } return 0; }

C

我在赛后过题挑战中取得了比赛一结束立刻就通过的好成绩,你也来试试吧~

这题手动模拟几次可以发现,如果给的那个最终序列最后一个位置是x,那么它的上一个序列其实就是这个序列的后x位移动到序列前面,给定最终序列,那么如此反向操作k次,结果是唯一的。

如果中间发现这个最后一个数x>n,那么就说明不可能。

如果我们想模拟这个反向操作,可以把序列复制很多次,也可以用模运算,具体见代码:

#include<iostream>
using namespace std;
const int maxn = 200200;
#include<unordered_map>
#include<string>
#include<cstring>
long long a[maxn];
int main()
{
int t;
cin >> t;
int tt = t;
while (t--)
{
memset(a, 0, sizeof a);
long long n, k;
cin >> n >> k; for (int i = 0; i <n; i++)
{
cin >> a[i];
} int flag = 1;
long long count = 0;
unordered_map<long long, long long >num;
for (long long i = n - 1; count <k;i=((i-a[i])+n)%n) //count<k而不是<=k,因为要求是正好k次
{
if (a[i]>n)
{ flag = 0;
break;
}
count++;
if (num.count(i) != 0) //遇到了重复下标,说明进入一个循环的过程了,就一定可以
{
flag = 1;
break;
}
num[i]++;
}
if (flag == 1)cout << "Yes" << endl;
else if(flag==0)cout << "No" << endl; } return 0;
}

分割线,赛时就想出来了这三道题,C题还因为<=k这个愚蠢bug没调出来,后面是补题,待更新

D

首先,最长上升子序列的长度一定不会变小,因为无论怎么加,原本的序列相对位置不变,所以至少可以取和原本一样的最长上升子序列

写成式子就是:LIS(C)>=LIS(A)

然后是LIS(C)<=LIS(A)+1,因为将b序列从大到小插入到A序列中的某一个位置,b序列对于A的LIS的增长贡献不会超过1,因为新加入的这些元素两两不能位于同一个上升子序列,所以说这样加入的B序列里面最多有一个数会使得A的某个上升子序列加1

下面考虑是否可以让LIS(C)==LIS(A),是可以的,和刚才的考虑类似,即按照不能位于同一上升子序列来考虑,假设只插入一个数x,那么要么这个数小于所有的数,把它放到最后,就不会让LIS增加,要么这个数不是最小的,那么可以找到一个比他小的数y,把x插入到y的前一个位置,这样x和y不可能出现在同一个出现在同一个上升子序列中,那么插入之后所有的包含x的上升子序列都可以把x用y来代替,即x的插入不会改变上升子序列的长度。那么对于B序列的所有元素都这么做,为了方便并且防止b序列完整进入A序列自身产生上升子序列,我们让每个数插入到第一个比他小的数前面,那么最终的结果就是把B倒序排序,然后和A序列进行一种类似归并排序的过程(C++甚至有merge函数可以完成)

代码如下:

#include <bits/stdc++.h>

using namespace std;

int main()
{
int t;
cin >> t; while (t--)
{
int n, m;
cin >> n >> m; vector<int> a(n), b(m); for (int i = 0; i < n; i++)
cin >> a[i];
for (int i = 0; i < m; i++)
cin >> b[i]; sort(b.begin(), b.end(), greater<int>());
int i = 0, j = 0;
vector<int> c(n + m);
int k = 0;
while (i < n && j < m)
{
if (a[i] > b[j])
{
c[k] = a[i++];
k++;
}
else
{
c[k] = b[j++];
k++;
}
} while (i < n)
{
c[k++] = a[i++];
}
while (j < m)
{
c[k++] = b[j++];
} for (int jk = 0; jk < n + m; jk++)
{
cout << c[jk] << " ";
}
cout << endl;
} return 0;
}

E

应该算是一种贪心做法,假定最后的集合大小是len,从题意中可以想到肯定有len的集合要少取,没有len的集合要多取,对于每个len可以用这样的一个大致的策略求得一个值,然后取最小。那么len一共有多少个呢,定义sumn,suml,sumr为n,l,r的求和,那么lne的范围应该是suml~sumr,也就是一共有sumr-suml+1种len,而X集合里面可能出现的元素种类只有sumn,如果len的种类数多余集合X中的可能的元素种类数,那么根据抽屉原理,一定可以在len的若干个可能取值中找到至少一个不会出现在X中的值,那么这种情况答案就是0,也就是说,如果sumr-suml+1>sumn,那么答案就是0

那如果sumr-suml+1<=sumn,就得按照贪心策略来取,首先是,对于不含len的集合,必须取满上限r,然后对于含有len的集合,我们可以根据题给的c数组确定len在这个集合有多少个,然后能够得出在这个集合中有多少个‘非len’,如果‘非len’的个数很少,甚至不足以选够l,那么我们为了满足l这个限制就不得不取l-not_len个len,如果‘非len’的个数足够取l,那么我么尽可能多的取‘非len’.这样取完之后,看此时填充到X中的个数,如果不够len,就意味着必须再从那些‘非len’不够的集合继续取一些len

代码如下

#include <bits/stdc++.h>
using namespace std;
#define int long long // 数据很大,会爆int
signed main()
{
int t;
cin >> t; while (t--)
{
int m;
cin >> m;
long long sumn = 0, suml = 0, sumr = 0;
vector<int> n(m), l(m), r(m);
vector<vector<int>> a(m);
vector<vector<int>> c(m);
vector<int> sumc(m); // 记录每个集合的元素总个数
for (int i = 0; i < m; i++)
{ cin >> n[i] >> l[i] >> r[i];
sumn += n[i];
suml += l[i];
sumr += r[i]; a[i].resize(n[i]); // 第i个集合的大小为n[i]
c[i].resize(n[i]);
for (int j = 0; j < n[i]; j++)
{
cin >> a[i][j];
}
for (int j = 0; j < n[i]; j++)
{
cin >> c[i][j];
sumc[i] += c[i][j];
}
} if (sumr - suml > sumn)
{
cout << 0 << endl;
/*
X集合的元素个数的范围是suml~sumr,它有sumr-suml+1种取值,
而所有集合的元素种类数最多sumn种
如果sumr-suml+1>sumn
那么sumr-suml+1个数字里面一定至少有一个数是sumn种数里没有的
抽屉原理
*/
continue;
} else
{ unordered_map<long long, long long> sum_have; // sum_have[asdf]记录含有asdf这个值的集合如果全都选满r个,共选了多少个
unordered_map<long long, vector<pair<int, int>>> indexs; // indexs记录的是某个值在所有集合中出现了多少次,位置在哪 for (int i = 0; i < m; i++)
{
for (int j = 0; j < n[i]; j++)
{
sum_have[a[i][j]] += r[i];
indexs[a[i][j]].push_back({i, j});
}
}
// 选的策略是,含有len的,如果非len少于l就按照l选,如果非len多就尽可能多选非len,不含len的按照r来选,如果这样选之后不到len,那么只能再往里加若干个len
long long ans = (int)2e18;
for (long long len = suml; len <= sumr; len++)
{
long long xsize = 0; // 表示的是集合X的元素个数
long long have_to_choose_len = 0; // 不得不选的len的个数,也就是说某个集合中非len值太少,甚至不够l xsize = sumr - sum_have[len]; // 集合X的个数初始化为:所有不含len的集合都按照r选
// 所有集合都选满r的值减去这个sumr_a[len]就是所有不含len的集合全部选满r的值
for (auto &[i, j] : indexs[len]) // 便利len出现的集合
{
int not_len = sumc[i] - c[i][j]; // 第i个结合中,所有元素的个数减去len在这里面的个数就是不是len的个数 if (not_len < l[i]) // 如果这个集合中非len元素甚至不够l,那么不得不选一些len
{
xsize += l[i];
have_to_choose_len += l[i] - not_len;
}
else
{
xsize += min(not_len, r[i]); // 如果非len值,尽可能多选非len值
}
}
ans = min(ans, have_to_choose_len + max(0LL, len - xsize));
// 对于每个len的答案就是必须选的值为len的答案(某个集合不等于len的值太少了,要选满至少l个不得不在这个集合选值为len的)
// 加上当前已经按照这个策略选的xsize和目标len之间的差值,如果当前的xsize还不够len,那么那些含有len的集合中不得不在选了l个之后继续选一些len
}
cout << ans << endl;
}
}
}

cf908(div2)题解(补题)的更多相关文章

  1. CCPC-Wannafly Winter Camp Day8 (Div2, onsite) 补题

    A Aqours 题解: https://www.cnblogs.com/qieqiemin/p/11251645.html D:吉良吉影的奇妙计划 (暴力打表) 题目描述 吉良吉影是一个平凡的上班族 ...

  2. 2018 HDU多校第四场赛后补题

    2018 HDU多校第四场赛后补题 自己学校出的毒瘤场..吃枣药丸 hdu中的题号是6332 - 6343. K. Expression in Memories 题意: 判断一个简化版的算术表达式是否 ...

  3. 2018 HDU多校第三场赛后补题

    2018 HDU多校第三场赛后补题 从易到难来写吧,其中题意有些直接摘了Claris的,数据范围是就不标了. 如果需要可以去hdu题库里找.题号是6319 - 6331. L. Visual Cube ...

  4. [数]补题ver.

    上次补题好像把两次训练混在一起了,总之先按时间顺序补完这一次|ू・ω・` ) HDU-6301 不会的东西不能逃避.jpg 红小豆非常讨厌构造题,因为非常不会,并且非常逃避学习这类题,因为总也搞不清楚 ...

  5. 4.30-5.1cf补题

    //yy:拒绝转载!!! 悄悄告诉你,做题累了,去打两把斗地主就能恢复了喔~~~ //yy:可是我不会斗地主吖("'▽'") ~~~那就听两遍小苹果嘛~~~ 五一假期除了花时间建模 ...

  6. CF Educational Round 78 (Div2)题解报告A~E

    CF Educational Round 78 (Div2)题解报告A~E A:Two Rival Students​ 依题意模拟即可 #include<bits/stdc++.h> us ...

  7. 【cf补题记录】Codeforces Round #608 (Div. 2)

    比赛传送门 再次改下写博客的格式,以锻炼自己码字能力 A. Suits 题意:有四种材料,第一套西装需要 \(a\).\(d\) 各一件,卖 \(e\) 块:第二套西装需要 \(b\).\(c\).\ ...

  8. 【cf补题记录】Codeforces Round #607 (Div. 2)

    比赛传送门 这里推荐一位dalao的博客-- https://www.cnblogs.com/KisekiPurin2019/ A:字符串 B:贪心 A // https://codeforces.c ...

  9. 【春训团队赛第四场】补题 | MST上倍增 | LCA | DAG上最长路 | 思维 | 素数筛 | 找规律 | 计几 | 背包 | 并查集

    春训团队赛第四场 ID A B C D E F G H I J K L M AC O O O O O O O O O 补题 ? ? O O 传送门 题目链接(CF Gym102021) 题解链接(pd ...

  10. CF1169(div2)题解报告

    CF1169(div2)题解报告 A 不管 B 首先可以证明,如果存在解 其中必定有一个数的出现次数大于等于\(\frac{m}{2}\) 暴力枚举所有出现次数大于等于$\frac{m}{2} $的数 ...

随机推荐

  1. 【Maven】POM基本概念

    目前的技术在开发中存在的问题: 一个项目就是一个工程 如果项目非常庞大,就不适合继续使用 package 来划分模块.最好是每一个模块对应一个工程,利于分工协作. 借助于 Maven 就可以将一个项目 ...

  2. Netty源码—10.Netty工具之时间轮

    大纲 1.什么是时间轮 2.HashedWheelTimer是什么 3.HashedWheelTimer的使用 4.HashedWheelTimer的运行流程 5.HashedWheelTimer的核 ...

  3. 『Plotly实战指南』--饼图绘制高级篇

    在数据可视化的世界里,饼图是最直观的展示比例关系的工具之一. 然而,传统的静态饼图已经无法满足现代数据分析的需求.Plotly作为一款强大的可视化库,不仅提供了饼图丰富的基础功能,还支持交互效果和动态 ...

  4. 我要成为node_modules大师!(一):包管理器选择,依赖关系分析

    好家伙 1.npm曾经的一些问题 1. 依赖地狱(Dependency Hell) 嵌套依赖结构:早期版本的 npm 采用嵌套的 node_modules 结构,依赖层级极深,容易导致路径过长问题(尤 ...

  5. 学习Kotlin语法(一)

    简介 Kotlin是一种现代.简洁且功能强大的编程语言,特别适合Android开发.本文将从基础语法开始,逐步掌握Kotlin的核心特性. 目录 变量 基本类型 数字 无符号对应项 布尔值 字符和字符 ...

  6. MYSQL数据库 MariaDB断电恢复总结

    背景:本次是机房异常断电,导致数据库文件损坏.在数据库自启动之后频繁宕机,在多次尝试以后,总结了一下几种方法,及供参考. 1.mariadb服务器断电重启之后Missing MLOG_CHECKPOI ...

  7. ApplicationContext 接口的实现类

    ClassPathXmlApplicationContext: 它是从类的根路径下加载配置文件 推荐使用这种 FileSystemXmlApplicationContext: 它是从磁盘路径上加载配置 ...

  8. 再见,SSE!你好,Streamable HTTP!轻松开发 Streamable HTTP MCP Server

    大家好!我是韩老师. 之前和大家分享了三篇 MCP 相关的文章: Code Runner MCP Server,来了! 从零开始开发一个 MCP Server! 一键安装 MCP Server! 还是 ...

  9. IIS—503错误排查

    服务器返回503(IIS Service Unavailable HTTP Error 503. The service is unavailable.)+IIS常见优化设置策略 - Yuliang. ...

  10. Java日期格式化中的“YYYY”陷阱:为什么跨年周会让你的年份突然+1?.md

    结论先行 在Java中使用 YYYY-MM-dd 格式化日期时,若日期所在的周跨年,年份可能会被错误计算为下一年(如2021年12月26日显示为2022年).而使用 yyyy-MM-dd 会始终返回正 ...