Codeforces Round #555 (Div. 3)[1157]题解
不得不说这场div3是真的出的好,算得上是从我开始打开始最有趣的一场div3。因为自己的号全都蓝了,然后就把不经常打比赛的dreagonm的号借来打这场,然后...比赛结束rank11(帮dreagonm上蓝果然没有食言qwq)。
(震惊...HA省A队CF青名...)
upd:system test
之后的最终排名是rank9,dreagonmTQL!!!
CF1157A Reachable Numbers
水题,分析一下不难发现不超过\(10\)次就会少一位,然后\(10^9\)范围内的数可以到达的数个数显然不多,不妨大力模拟,然后把出现的数扔进set
,最后输出set.size()
即可。(开到\(10^6\)不会T也不会有被卡次数的危险)
#include<bits/stdc++.h>
using namespace std;
int n;
set<int>s;
int main(){
scanf("%d",&n);
for(int i=1;i<=1e6;i++){
s.insert(n);
n+=1;
while(n%10==0){
n/=10;
}
}
printf("%d\n",(int)s.size());
return 0;
}
CF1157B Long Number
注意是选择一段连续的区间,把区间内的数全部替换为映射值。不难发现可能会增大也有可能减小,为了让数尽可能变大,考虑采取贪心的策略,找到第一个能使得原数变大的位置\(l\),然后从这个位置向后找,找到第一个会变小的位置\(r\),则变化区间为\([l,r)\)。
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n;
char s[N];
int a[15];
char ans[N],t[N];
int fir,lst;
int main(){
scanf("%d",&n);
scanf("%s",s+1);
for(int i=1;i<=9;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++){
if(s[i]-'0'<a[s[i]-'0']){
fir=i;
break;
}
}
if(!fir){
printf("%s\n",s+1);
return 0;
}
for(lst=fir;lst<=n;lst++){
if(s[lst]-'0'>a[s[lst]-'0']){
lst--;
break;
}
}
if(lst>n){
lst=n;
}
for(int i=fir;i<=lst;i++){
s[i]='0'+a[s[i]-'0'];
}
printf("%s\n",s+1);
return 0;
}
CF1157C Increasing Subsequence
C1
显然,贪心就行了,因为选完小的还能选大的,答案不会变劣。
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n;
int a[N],now,l,r;
char op[N];
int cntop;
int main(){
scanf("%d",&n);
l=1;r=n;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
while(l<=r){
if(a[l]>now&&a[r]>now){
if(a[l]<a[r]){
op[++cntop]='L';
now=a[l];
l++;
}
else{
op[++cntop]='R';
now=a[r];
r--;
}
}
else if(a[l]>now){
op[++cntop]='L';
now=a[l];
l++;
}
else if(a[r]>now){
op[++cntop]='R';
now=a[r];
r--;
}
else{
break;
}
}
printf("%d\n%s\n",cntop,op+1);
return 0;
}
C2
和C1
不一样的是,不保证任意两两不同。那么考虑和C1
不同的点,不难发现在于两端的数的大小关系多了相等的情况,其他的也没什么不同。显然,如果两端相同,之后就只能从一边选,那么对于这种情况直接贪心选择最多的一边选即可。
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n;
int a[N],now,l,r;
char op[N];
int cntop;
int main(){
scanf("%d",&n);
l=1;r=n;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
while(l<=r){
if(a[l]>now&&a[r]>now){
if(a[l]==a[r]){
for(int i=l+1,j=r-1;;i++,j--){
if(a[i]<=a[i-1]){
while(a[r]>now){
op[++cntop]='R';
now=a[r];
r--;
}
break;
}
else if(a[j]<=a[j+1]){
while(a[l]>now){
op[++cntop]='L';
now=a[l];
l++;
}
break;
}
}
}
else if(a[l]<a[r]){
op[++cntop]='L';
now=a[l];
l++;
}
else{
op[++cntop]='R';
now=a[r];
r--;
}
}
else if(a[l]>now){
op[++cntop]='L';
now=a[l];
l++;
}
else if(a[r]>now){
op[++cntop]='R';
now=a[r];
r--;
}
else{
break;
}
}
printf("%d\n%s\n",cntop,op+1);
return 0;
}
CF1157D N Problems During K Days
这题挺有趣的,要求构造\(k\)个正整数和为\(n\),且满足对于\(1\leq i<k\),\(a_i<a_{i+1}\leq2a_i\)。从约束条件入手,分析下界可知,如果还有\(k\)个数需要确定,而第一个数为\(i\),那么这\(k\)个数在和最小的情况下分别是\(i,i+1,\cdots,i+k-1\),由此可得下界。分析上界可知,和最大的情况下分别是\(i,2i,2^2i,\cdots,2^{k-1}i\),和为\((2^k-1)i\),由此可得上界。因为第一个数可以无穷大但不能小于\(1\),所以约束主要是在下界,那么尽可能避免下界不合法即可,所以对于每个位置\(i\),使\(a_i\)尽可能小即可。以样例为例,n=8 k=3
时,如果\(a_1=1\),那么和最大为\(1+2+4=7\),显然过小。如果\(a_1=2\),和最小为\(2+3+4=9\),又过大了,那么就不合法。n=9 k=4
时,和最小为\(1+2+3+4=10\),亦过大。所以总的思路就是在和的上界不小于剩余的值的情况下选择最小的\(a_i=\max(\lceil\Large\frac{n}{2^{k-i+1}-1}\normalsize\rceil,a_{i-1}+1)\),然后判断在取得最小可能值的情况下会不会有下界不合法即可(因为取值已经保证上界合法)。
Trick:double
在存储\(2\)的次方是可以得到精确值,用pow(2.0,x)
就能得到精确的\(2^x\),就不需要再担心\(\large2^{10^5}\)过大的问题。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,k;
long long sum(int u){
return 1LL*u*(u+1)/2;
}
double sumb(int u){
return pow(2.0,u)-1;
}
int a[N];
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=k;i++){
int rep=max(a[i-1]+1,(int)ceil((double)n/sumb(k+1-i)));
if(sum(rep+k-i)-sum(rep-1)>n){
printf("NO\n");
return 0;
}
a[i]=rep;
n-=rep;
}
printf("YES\n");
for(int i=1;i<=k;i++){
printf("%d%c",a[i]," \n"[i==k]);
}
return 0;
}
CF1157E Minimum Array
题目意思是给出\(a,b\)两个数组,要求给\(b\)重新排序,使得\(c_i=(a_i+b_i)\bmod{n}\)的字典序最小。显然字典序是由高位开始比较的,所以显然可以贪心解决,只需要让前面的\(c_i\)尽可能小即可。由模运算的性质可知,每次找到不小于\(a_i\bmod{n}\)的相反数的最小数即可,如果不存在就选所有数的最小值。然后整个过程用multiset
维护\(b\)数组即可。
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n;
int a[N],b[N];
multiset<int>s;
int c[N];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++){
scanf("%d",&b[i]);
s.insert(b[i]);
}
for(int i=1;i<=n;i++){
int rep=(n-a[i])%n;
auto ite=s.lower_bound(rep);
if(ite==s.end()){
ite=s.begin();
}
c[i]=*ite;
s.erase(ite);
}
for(int i=1;i<=n;i++){
printf("%d%c",(a[i]+c[i])%n," \n"[i==n]);
}
return 0;
}
CF1157F Maximum Balanced Circle
题目意思是从给定的\(n\)个数中选尽可能多的数,使得这些数按照某种顺序放到环上后,相邻两个数的差不超过\(1\)。显然对于这道题可以先桶排,然后考虑选出的数中最小的数,如果选出的数最小值和最大值分别为\(l,r\),那么一定需要按照\(l,l+1,\cdots,r,r-1,\cdots,l\)排序,否则相邻相差就会大于\(1\)。那么不难发现,对于\(\forall i\in(l,r),cnt_i>1\)。由此,可以考虑枚举\(l\),求出最大的\(r\),显然,对于\(l'\in(l,r]\),如果将选出的数范围改为\([l',r]\),那么答案一定会比\([l,r]\)劣,所以枚举的时间复杂度为\(O(\max a_i)\)。然后考虑一下细节,处理\(l=r,l+1=r,l+1<r\)三种情况即可。
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,a[N],c[N],sum[N];
int ans;
int mx,l,r;
int query(int u,int v){
return sum[v]-sum[u-1];
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
++c[a[i]];
}
for(int i=1;i<2e5;i++){
if(c[i]&&c[i+1]){
ans=i;
break;
}
}
if(!ans){
for(int i=1;i<=2e5;i++){
if(c[i]>mx){
ans=i;
mx=c[i];
}
}
printf("%d\n",mx);
for(int i=1;i<=mx;i++){
printf("%d%c",ans," \n"[i==mx]);
}
return 0;
}
for(int i=1;i<=2e5;i++){
sum[i]=sum[i-1]+c[i];
}
for(int i=1,j;i<=2e5;){
if(!c[i]||!c[i+1]){
i++;
continue;
}
else if(c[i+1]==1){
if(mx<query(i,i+1)){
mx=query(i,i+1);
l=i;r=i+1;
}
i++;
}
else{
for(j=i+1;j<=n;j++){
if(c[j]>1){
continue;
}
else{
break;
}
}
if(!c[j]){
--j;
}
if(mx<query(i,j)){
mx=query(i,j);
l=i;r=j;
}
i=j;
}
}
printf("%d\n",mx);
for(int i=l;i<=r;i++){
printf("%d ",i);
}
for(int i=r;i>=l;i--){
for(int j=1;j<c[i];j++){
printf("%d ",i);
}
}
return 0;
}
CF1157G Inverse of Rows and Columns
题目要求求出对于给定的\(n\times m\)的\(01\)矩阵,是否有选择某些行/列进行反转后使得按照\(a_{11},a_{12},\cdots,a_{1n},a_{21},\cdots,a_{nn}\)顺序排列后有序的方案,如果有则输出任意可行方案。观察到题目限制条件,易知合法变化后的矩阵应当至多有一行既有\(0\)也有\(1\),如果有则在这一行之前的所有行均为\(0\),之后的所有行均为\(1\),如果不存在既有\(0\)也有\(1\)的行则前一部分行全为\(0\),后一部分全为\(1\)。观察到数据范围\(n,m\leq200\),不妨暴力枚举按题目顺序展开后的第一个\(1\)的位置,然后检验是否有可行的方案即可。
#include<bits/stdc++.h>
using namespace std;
const int N=220;
int n,m;
int opa[N],opb[N];
int a[N][N],b[N][N];
bool can(int u,int v){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(i<u||(i==u&&j<v)){
b[i][j]=0;
}
else{
b[i][j]=1;
}
}
}
opa[1]=a[1][1]^b[1][1];
for(int i=1;i<=m;i++){
opb[i]=a[1][i]^b[1][i]^opa[1];
}
for(int i=2;i<=n;i++){
opa[i]=a[i][1]^b[i][1]^opb[1];
for(int j=2;j<=m;j++){
if(b[i][j]!=(a[i][j]^opa[i]^opb[j])){
return 0;
}
}
}
return 1;
}
void print(){
printf("YES\n");
for(int i=1;i<=n;i++){
putchar('0'+opa[i]);
}
putchar('\n');
for(int i=1;i<=m;i++){
putchar('0'+opb[i]);
}
putchar('\n');
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&a[i][j]);
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(can(i,j)){
print();
return 0;
}
}
}
printf("NO\n");
return 0;
}
Codeforces Round #555 (Div. 3)[1157]题解的更多相关文章
- # Codeforces Round #529(Div.3)个人题解
Codeforces Round #529(Div.3)个人题解 前言: 闲来无事补了前天的cf,想着最近刷题有点点怠惰,就直接一场cf一场cf的刷算了,以后的题解也都会以每场的形式写出来 A. Re ...
- Codeforces Round #557 (Div. 1) 简要题解
Codeforces Round #557 (Div. 1) 简要题解 codeforces A. Hide and Seek 枚举起始位置\(a\),如果\(a\)未在序列中出现,则对答案有\(2\ ...
- Codeforces Round #540 (Div. 3) 部分题解
Codeforces Round #540 (Div. 3) 题目链接:https://codeforces.com/contest/1118 题目太多啦,解释题意都花很多时间...还有事情要做,就选 ...
- Codeforces Round #538 (Div. 2) (A-E题解)
Codeforces Round #538 (Div. 2) 题目链接:https://codeforces.com/contest/1114 A. Got Any Grapes? 题意: 有三个人, ...
- Codeforces Round #531 (Div. 3) ABCDEF题解
Codeforces Round #531 (Div. 3) 题目总链接:https://codeforces.com/contest/1102 A. Integer Sequence Dividin ...
- Codeforces Round #527 (Div. 3) ABCDEF题解
Codeforces Round #527 (Div. 3) 题解 题目总链接:https://codeforces.com/contest/1092 A. Uniform String 题意: 输入 ...
- Codeforces Round #499 (Div. 1)部分题解(B,C,D)
Codeforces Round #499 (Div. 1) 这场本来想和同学一起打\(\rm virtual\ contest\)的,结果有事耽搁了,之后又陆陆续续写了些,就综合起来发一篇题解. B ...
- Codeforces Round #545 (Div. 1) 简要题解
这里没有翻译 Codeforces Round #545 (Div. 1) T1 对于每行每列分别离散化,求出大于这个位置的数字的个数即可. # include <bits/stdc++.h&g ...
- Codeforces Round #624 (Div. 3)(题解)
Codeforces Round #624 (Div.3) 题目地址:https://codeforces.ml/contest/1311 B题:WeirdSort 题意:给出含有n个元素的数组a,和 ...
随机推荐
- ModelAttribute用法之一
@ModelAttribute也可以做为Model输出到View时使用,比如: 测试例子 package com.my.controller; import java.util.ArrayList ...
- Vue基本使用和指令集
Vue的使用 一.安装 对于新手来说,强烈建议大家使用<script>引入: 二. 引入vue.js文件 我们能发现,引入vue.js文件之后,Vue被注册为一个全局的变量,它是一个构造函 ...
- Tomcat web.xml配置参数详解
Apache Tomcat Configuration Reference - The Context Containerhttps://tomcat.apache.org/tomcat-5.5-do ...
- Azure系列2.1.2 —— BlobContainerProperties
(小弟自学Azure,文中有不正确之处,请路过各位大神指正.) 网上azure的资料较少,尤其是API,全是英文的,中文资料更是少之又少.这次由于公司项目需要使用Azure,所以对Azure的一些学习 ...
- FindBugs-IDEA插件的使用
前言 Findbugs很多人都并不陌生,Eclipse中有插件可以帮助查找代码中隐藏的bug,IDEA中也有这款插件.这个插件可以帮助我们查找隐藏的bug,比较重要的功能就是查找潜在的null指针. ...
- 莫烦sklearn学习自修第九天【过拟合问题处理】
1. 过拟合问题可以通过调整机器学习的参数来完成,比如sklearn中通过调节gamma参数,将训练损失和测试损失降到最低 2. 代码实现(显示gamma参数对训练损失和测试损失的影响) from _ ...
- Yii2的save()方法容易出错的地方
如果save()返回true, 但是数据没有保存成功,则应该是开启了事务且已经回滚 如果save()返回false, 则使用$model->errors查看错误原因 可以设置$model的场景, ...
- 在Mac 系统上使用MAMP搭建PHP开发环境
1.下载MAMP套件 下载地址为https://www.mamp.info/en/ 2.安装此.dmg文件 3.配置apache虚拟主机 (1)在/Applications/MAMP/conf/apa ...
- timestamp 与 nonce 防止重放攻击
重放攻击是计算机世界黑客常用的攻击方式之一,所谓重放攻击就是攻击者发送一个目的主机已接收过的包,来达到欺骗系统的目的,主要用于身份认证过程. 首先要明确一个事情,重放攻击是二次请求,黑客通过抓包获取到 ...
- PHPStorm 配置命名空间
文件-设置-Directories 选中:application 点击顶部:Sources,右侧会出现 Source Floders 配置项 点击:p进行设置 输入app\