第一次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. ShardingSphere 解决关联表查询问题的详细方案

    一.基础概念 在分库分表场景下,关联表(JOIN)查询的复杂性主要源于数据分布在不同的数据库或表中.ShardingSphere 通过 绑定表(Binding Table) 和 广播表(Broadca ...

  2. 康谋分享 | aiSim5 物理相机传感器模型验证方法(一)

    摘要: aiSim5可以实时模拟复杂的传感器配置,在多GPU分布式渲支持的支持下,aiSim可以渲染20多个摄像头.10多个雷达和10多个激光雷达在同一环境下运行.aiSim5独有的实时渲染引擎能够满 ...

  3. 重生之我是操作系统(十)----I/O管理

    简介 操作系统的I/O管理(input/output mannagment)是协调,控制计算机与外部设备(如磁盘,键盘,网络接口)等之间数据交换的核心功能.实现可靠高效且统一(隐藏设备差异,如磁盘.串 ...

  4. [开源] Layouter(桌面助手)开源发布

    Layouter(桌面助手)是一款简洁.易用.美观的桌面整理软件,基于.net 6开发,支持Windows 7及以上操作系统.以 Apache-2.0 license 进行开源. 开源地址 https ...

  5. Web前端入门第 39 问:细说 CSS position 定位布局

    CSS 的定位属性 position 可以把元素从文档流中拧出来,让其显示在其他位置. 但凡元素定位属性加身,元素位置便不再受文档流控制,这时候什么 flex.grid 都不好使了,定位的元素已然跳出 ...

  6. Asp.net core 少走弯路系列教程(六)C# 语法学习

    前言 新人学习成本很高,网络上太多的名词和框架,全部学习会浪费大量的时间和精力. 新手缺乏学习内容的辨别能力,本系列文章为新手过滤掉不适合的学习内容(比如多线程等等),让新手少走弯路直通罗马. 作者认 ...

  7. 【FAQ】HarmonyOS SDK 闭源开放能力 — PDF Kit

    1.问题描述: 预览PDF文件,文档上所描述的loadDocument接口,可以返回文件的状态,并无法实现PDF的预览,是否有能预览PDF相关接口? 解决方案: 1.执行loadDocument进行加 ...

  8. 集合流之“anyMatch”的应用【返回boolean类型】

    判断集合中是否存在"字符串",返回boolean类型 boolean isExit = allSku.stream().map(Product::getFeatureList) . ...

  9. dotnet-trace 分析.net程序性能

    在现代 .NET 开发中,性能分析和故障诊断是确保应用程序稳定性和高效性的关键步骤. 本文将介绍如何使用 dotnet-trace 工具进行 .NET Core 应用的性能跟踪,并结合 PerfVie ...

  10. C#之可访问性约束(可访问性不一致)

    C# 语言中的有些构造要求某个类型至少与某个成员或其他类型具有同样的可访问性 (at least as accessible as).如果 T 的可访问域是 M 可访问域的超集,我们就说类型 T 至少 ...