Educational Codeforces Round 161 (Rated for Div. 2)补题

Tricky Template(Problem - A - Codeforces)

题目大意:现有三个模板字串a,b,c,都由小写字母组成,问能否找到一个字串s,使s与a,b匹配,与c不匹配,匹配的条件如下:

如果s的某位为小写字母,那么需要与匹配串的对应位完全相同

如果某位为大写字母,那么需要与匹配串的对应位不同

思路:这题的考点就在于什么时候出现题目要求的情况,只要有一位满足,哪怕剩下的不满足也无所谓,那么就要看a[i],b[i],c[i]的关系,如果a[i]=b[i]=c[i],那么这一位能与a,b匹配就一定能与c匹配,如果a[i]=b[i]!=c[i],那么填上a[i]即可,如果如果a[i]!=b[i],这一位可以填一个大写字母,这个大写字母与c[i]相同但不与a[i],b[i]相同即可,也就是说,只要有一个位置a[i]!=c[i]&&b[i]!=c[i]就成立。

#include<bits/stdc++.h>
using namespace std;
int main()
{int t;scanf("%d",&t);while(t--){int n;string a,b,c;cin>>n>>a>>b>>c;int flag=0;for(int i=0;i<n;i++){if(a[i]!=c[i]&&b[i]!=c[i]) {flag=1;break;}}if(flag) printf("YES\n");else printf("NO\n");}
}

Forming Triangles(Problem - B - Codeforces)

题目大意:现给出若干条边,每条边的长度为2^a[i],要找出三边组成一个三角形(非退化三角形就是一个有面积的三角形),问最多有多少种组合(数相同,但所处位置不同视为不同的选择)

思路:这里提到了2^a[i],那么就要从二进制的角度来看看有什么规律:

2^i=2^(i-1)+2^(i-1) 

 然后又由三角形两边之和大于第三边,所以我们必须选两个相同的,然后再选一个小于等于它们的。那么情况实际就出来了,先统计出每种长度边的个数,用map统计,刚好还能顺便排个序。然后从小到大访问,对于每种长度,如果大于等于2才有讨论的价值,选出两条当前长度的边,假设当前长度的有k条边,那么这两条边的选择的情况就有(k-1)*k/2,然后第三条边的选择为前c条边的总个数+(k-2),那么遍历map就能统计出来。

#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main()
{int t;scanf("%lld",&t);while(t--){int n;scanf("%lld",&n);map<int,int>mp;for(int i=1;i<=n;i++) {int x;scanf("%lld",&x);mp[x]++;}int c=0;int ans=0;for(auto it:mp){int d=it.second;if(d>=2){ans += (d-1)*d/2*c;//前面的ans += (d-2)*(d-1)*d/6;//本身}c+=d;}printf("%lld\n",ans);}
}

Closest Cities(Problem - C - Codeforces)

题目大意:现有一排城市,它们的坐标单增,然后每个城市有一个最近城市(距离绝对值是这个城市到所有城市中最小的),对于城市x,如果要到城市y,那么有两种情况:

y是x的最近城市:花费1;

y不是x的最近城市:花费abs(ax-ay)

现有q个查询,a,b,求a到b的最小花费。

思路:我们来看从a到b,如果直接走,由于坐标单增,实际上相当于一个点一个点走,两点之间花费为坐标差,或者1,因为单增,所以不会重复计算某一段。然后有q个询问,那么我们只要预处理出来从前到后和从后到前的前缀和不就好了。

#include<bits/stdc++.h>
using namespace std;
int a[200010],ne[200010],s1[200010],s2[200010];
signed main()
{int t;scanf("%d",&t);while(t--){int n;scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%d",&a[i]);ne[1]=2,ne[n]=n-1;for(int i=2;i<=n-1;i++){int l=a[i]-a[i-1],r=a[i+1]-a[i];if(l<r) ne[i]=i-1;else ne[i]=i+1;}s1[1]=0;int c=1;for(int i=2;i<=n;i++){if(ne[c]==i) s1[i] = s1[c]+1;else s1[i] = s1[c]+a[i]-a[c];c=i;}s2[n]=0;c=n;for(int i=n-1;i>=1;i--){if(ne[c]==i) s2[i]=s2[c]+1;else s2[i]=s2[c]+a[c]-a[i];c=i;}int q;scanf("%d",&q);while(q--){int l,r,ans=0;scanf("%d%d",&l,&r);if(l<r)ans = s1[r]-s1[l];elseans=s2[r]-s2[l];printf("%d\n",ans);}}
}

 ps:这里我最初还想的是给每个点和它可以到的点打上标记,然后判断标记是否相同(来自Salyg1n and the MEX Game(Problem - C - Codeforces),包括画的有向图的想法也来自这里),然后后来又想到遍历每个点,以每个点作为中转(来自最长上升子序列状态转移的思路),再后来又想到找离它们最近的标记相同的点(来自2D Traveling(Problem - B - Codeforces)),再往后发现找起来太麻烦,然后发现性质,打算遍历,然后超时了,想到前缀和优化,然后ac。所以,思路未必是一次就想到的,就是这样不断猜测不断尝试不断推翻最后实现的过程。而且这每一步其实都是联想到之前题目的解法类比出来的,所以呀,哪有什么捷径,都是不断学习新的知识点,不断补题学习新思路,不断内化,然后转为输出的过程。

Berserk Monsters(Problem - D - Codeforces)

题目大意:现在有n个怪兽排成一排,每个怪兽有一个攻击值a和一个防御值d,对它们发动魔法攻击,它们可以同时对相邻位置的怪兽产生a的伤害,如果一个怪兽受到的伤害值大于d,那么这个怪兽就死亡,游戏进行n轮,要求每轮死亡怪兽的数目。

思路:乍一看很简单,就是一个双向链表的题,可以定义l[],r[]两个数组来表示指针,单独定义一个数组储存它们受到的伤害,最后链表遍历结束时,遍历怪兽,将受到伤害的怪兽移出链表。看起来很对,也确实可以实现,但是这里的时间复杂度就是O(n^2),因为回合是n轮,每次遍历怪兽判断是否死亡的时间复杂度也是O(n),那么合起来就是O(n^2),有没有什么办法可以进行优化呢?显然是有的,我们可以发现怪兽左边相邻的怪兽的下标一定比它小,右边相邻的怪兽的下标一定比它大。然后我们与删除位置相邻的怪兽的左右会变,别的怪兽的左右不会变,所以它原来如果没被删除,那么将可以删除的部分删除后,它们仍然不会被删除,那么就没有遍历的必要。所以我们将删除位置左右没被删除的元素记录下来即可。再次遍历时,就只访问这些元素。然后再来看,我们如何去删除元素呢,显然用:

r[l[i]]=r[i]

l[r[i]]=l[i]

那么我们如果有三个元素a,b,c,相邻的两个元素b,c都被删除,岂不是a被被放进新数组两次,这也产生了冗余,那就需要用到vector容器的两个函数unique(),resize(),unique()将所有元素调整一下,对于重复元素,取一个放到前面来,剩下的都放在后面,结束时,返回不重复部分尾元素的迭代器,resize()重新分配空间大小,所以就是g.resize(unique(g.begin(),g.end())-g.begin())即可实现,那么这道题的优化就完成了,我们只记录删除位置左右未被删除的元素,所以最坏情况是隔一个删一个那么每次砍半,但是并不会真的出现这种情况,所以时间复杂度是小于O(nlogn)的,可以AC。

#include<bits/stdc++.h>
using namespace std;
int a[300010],d[300010],l[300010],r[300010],st[300010];
int main()
{int t;scanf("%d",&t);while(t--){int n;scanf("%d",&n);vector<int>g,v;for(int i=1;i<=n;i++) {scanf("%d",&a[i]);g.push_back(i);l[i]=i-1;r[i]=i+1;st[i]=1;}a[n+1]=0;r[n]=0;for(int i=1;i<=n;i++) scanf("%d",&d[i]);for(int k=0;k<n;k++){sort(g.begin(),g.end());//O(mlogm),m<=ng.resize(unique(g.begin(),g.end())-g.begin());O(m),m<=nfor(auto it:g)O(m),m<=n{if(d[it]<a[l[it]]+a[r[it]]){v.push_back(it);st[it]=0;}}g.clear();for(auto i:v)//O(m),m<=n{/*这里实际上只考虑原来位置删除后,新产生的相邻关系会不会造成删除,原来不能删的,如果相邻元素没变,一样不能删,没有考虑的必要,原来能删的已经删除,自然不会被放入,所以g一下被缩小到很小,最坏隔一位删一个,那么就变成一半,剩余的都比一半小,所以最坏是logn,而且肯定不到logn*/l[r[i]]=l[i],r[l[i]]=r[i];if(st[l[i]]) g.push_back(l[i]);if(st[r[i]]) g.push_back(r[i]);}cout<<v.size()<<" ";v.clear();}cout<<endl;}
}

Increasing Subsequences(Problem - E - Codeforces)

题目大意:现在要创建一个数组,使数组中的严格上升子序列的个数恰好为x个。输出数组长度和具体的数,如果不成立则输出-1.另外数组长度不能超过200。

思路:这个题按照题目意思来看,这个数组可以是任意的,所以正着想不大好想,似乎没什么规律,那么我们倒着来看,如何统计一个序列中单增序列的个数,这里显然需要用到动态规划:

dp[i]表示以i作为结尾的单增序列的个数,那么就如下更新:

dp[i]=1(前面一个序列都不加)

dp[i]+=dp[x](1<=x<v,如果a[i]>a[x])

我们就此找出每个位置可以产生的上限,进而算出总的最大值,因为要考虑是否可以产生这样的数组

max:

dp[1]=1;

dp[2]=1+dp[1]=2;

dp[3]=1+dp[1]+dp[2]=4;

dp[4]=1+dp[1]+dp[2]+dp[3]=8;

... 

 是不是有点特点,某个位置前面如果有多少个小于它的数,那么就可以产生2多少次方个贡献。

所以我们考虑将n转化成二进制的角度来看,我最开始的思路是通过将高位转化到低位,然后按照

v,v+1,...,v+k,v,v+1,v+2,...

的顺序来放,每一组内部包含一个所有位。

但是很显然长度会超,那么我们在找找别的规律来看:

以37为例:

100101

空也为一种情况,所以凑出36即可

100100

如果将最高位拆下来:011212

再举一个偶数来看:

36

则需凑出35:

100011

如果将最高位拆下来:011123;

我们会发现拆的时候除了最后一位和原本是1的地方外,其他都是1,为1则表示前面有多少个小于它的数,那么我们可以设定一个单增的序列:

1 2 3 4 5 5

那么得到的单增序列长度为:1 2 4 8 16 16

这样可以看出,1和2都能对应凑出来,如果为3的话,也是最后一位为3,前面有0个小于它的数,那么直接开头填一个最大值即可。

那么思路就有了,我们直接拆太麻烦,就看原数的每位数的前一位(从右往左访问),如果为1,那么在添完本位数后,后面多填一个最大的数,这样就可以保证下一位有两个。这样看实际0位,如果原数是偶数,那么0位就是0,最后应该有两个数前面有0个元素小于它,一个是我们填进去的第一个元素,一个代表空集合。如果原数是奇数,那么这一位实际应该有3个数前面有0个元素小于它,除了刚提到的两个,我们再多加一个最大数即可。

#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main()
{int t;scanf("%lld",&t);while(t--){int n;scanf("%lld",&n);int k=__lg(n);//二进制下最高位1在哪里vector<int>g;if(n%2) g.push_back(k);//出了空还多一个1for(int i=0;i<k;i++){g.push_back(i);if(n>>i+1&1 && i+1!=k) g.push_back(k);}cout<<g.size()<<endl;for(auto i:g) cout<<i<<" ";cout<<endl; }
}

 ps:哈哈哈,这次终于轮到我卡着最后一分钟ac了。所以哪有什么应不应该,没思路就去想思路,有思路了就去实现思路,那么ac是必然的事情,只要还没结束,那么就不要认输放弃,说不定下一秒就写出来了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/633531.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

边缘计算和联邦学习的联系

1. 什么是边缘计算&#xff1f; 边缘计算&#xff08;Edge Computing&#xff09;是一种计算模型&#xff0c;其主要思想是将计算、存储和数据处理能力推送到离数据源近的边缘设备&#xff0c;而不是依赖于远程的云服务器。这样做的目的是减少数据传输延迟、提高响应速度&…

web前端项目-中国象棋【附源码】

中国象棋 【中国象棋】是一款历史悠久、深受人们喜爱的策略类游戏。在Web前端技术中&#xff0c;我们可以使用HTML、CSS和JavaScript等语言来制作一款中国象棋游戏。玩家使用棋子&#xff08;帅/相/士/炮/马/车/炮/卒&#xff09;在棋盘上相互对弈&#xff0c;将对手的“帅”棋…

工作流管理框架airflow-安装部署教程

1 概述 Airflow是一个以编程方式编写&#xff0c;用于管理和调度工作流的平台。可以帮助你定义复杂的工作流程,然后在集群上执行和监控这些工作流。 Airflow计划程序在遵循指定的依赖项&#xff0c;同时在一组工作线程上执行任务。丰富的命令实用程序使在DAG上执行复杂的调度…

国产开源模型标杆,能力比肩ChatGPT!书生·浦语2.0发布,支持免费商用

1月17日&#xff0c;新一代大语言模型书⽣浦语2.0&#xff08;InternLM2&#xff09;正式发布并开源。 2种参数规格、3种模型版本&#xff0c;共计6个模型&#xff0c;全部免费可商用。 它支持200K超长上下文&#xff0c;可轻松读200页财报。200K文本全文范围关键信息召回准确…

Android13预装APP到data分区

修改步骤与Android11是差不多的&#xff0c;只是有部分代码所在位置不一样。 Android 11内置APP到data/app Android 8(O)预置APP到data/app 默认内置应用到data会出错 1970-01-01 08:03:54.499 1177-1177/system_process I/PackageManager: /data/app/xx changed; collecting…

Springboot日志框架logback与log4j2

目录 Springboot日志使用 Logback日志 日志格式 自定义日志格式 日志文件输出 Springboot启用log4j2日志框架 Springboot日志使用 Springboot底层是使用slf4jlogback的方式进行日志记录 Logback日志 trace&#xff1a;级别最低 debug&#xff1a;调试级别的&#xff0c…

Windows平台反调试技术学习

前言 前俩天的学习记录Windows上面的反调试学习&#xff0c;主要是参考《恶意代码实战分析》和《加密与解密》里面的&#xff0c;给每个小技术都写了程序示例&#xff0c;自己编译反调试了一遍。对于加解密一书是还有很多不理解的地方的&#xff0c;目前只能记录到这了&#x…

Nodejs 问题排查

前言 用于记录在使用 node 过程中遇到的问题&#xff0c;并尝试寻求解决方案。 问题 问题1 问题描述 访问前端页面时&#xff0c;页面返回 502/504。查看日志后发现&#xff0c;在一些出现问题的时间节点&#xff0c;会出现以下日志&#xff1a; epoll_wait() reported t…

自己动手写数据库系统:解释执行 update 和 delete 对应的 sql 语句

在上一节我们完成了 select 语句的解释执行&#xff0c;本节我们看看 Update 和 Delete 对应的语句如何解释执行&#xff0c;当然他们的实现原理跟我们前面实现的 select 语句执行大同小异。无论是 update还是 delete 都是对数据表的修改&#xff0c;因此他们的实现方法基本相同…

建筑类中级工程师职称证明业绩材料有哪些?

三、建筑类中级工程师职称造价类工程业绩材料 1.合同&#xff1a;证明项目合作关系的凭证。 2.预&#xff08;结&#xff09;算报告等(重点是体现封面有你的名字和执业印章等) 3.单位证明或任命书(本人在项目中的职务聘书) 4.工程获奖证明&#xff1a;项目获得市优的证书、省优…

Ubuntu 22.04.1 LTS VirtualBox7.0 解决虚拟机窗口失去焦点一段时间后,虚拟机显示不刷新问题

故障描述&#xff1a; virtualbox安装在ubuntu系统上&#xff0c;虚拟机内安装了windows操作系统。使用中发现&#xff0c;当linux系统窗口被激活&#xff0c;如firefox浏览器&#xff0c;虚拟机的显示一段时间后会暂停刷新&#xff0c;鼠标划入虚拟机窗口后&#xff0c;才会立…

分布式概念

文章目录 一、CAP定理和BASE定理1.1 CAP定理1.2 CAP取舍1.3 BASE定理 二、分布式事务2.1 柔性事务2.2 两阶段提交协议2.3 三阶段提交协议 三、分布式ID3.1 数据库自增ID3.2 数据库多主模式3.3 号段模式3.4 雪花算法3.5 Leaf3.6 使用Redis生成ID 四、限流算法4.1 固定窗口计数器…

插入排序-insertSort

1、基本思路 与冒泡排序和插入排序一样&#xff0c;也是两个元素比较&#xff1b;不过不同的是&#xff0c;在插入排序中&#xff0c;数组的左边会维护一个有序数组&#xff0c;这个数组刚开始时只有一个元素&#xff0c;即数组第一个元素&#xff0c;后续将拿有序数组后的第一…

TypeScript实现一个贪吃蛇小游戏

游戏效果 文件目录 准备1&#xff1a;新建index.html&#xff0c;编写游戏静态页面 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-…

小程序开发实战案例五 | 小程序如何嵌入H5页面

在接入小程序过程中会遇到需要将 H5 页面集成到小程序中情况&#xff0c;今天我们就来聊一聊怎么把 H5 页面塞到小程序中。 本篇文章将会从下面这几个方面来介绍&#xff1a; 小程序承载页面的前期准备小程序如何承载 H5小程序和 H5 页面如何通讯小程序和 H5 页面的相互跳转 小…

安全加速SCDN是什么

安全加速SCDN&#xff08;Secure Content Delivery Network&#xff0c;SCDN&#xff09; 是集分布式DDoS防护、CC防护、WAF防护、BOT行为分析为一体的安全加速解决方案。已使用内容分发网络&#xff08;CDN&#xff09;或全站加速网络&#xff08;ECDN&#xff09;的用户&…

【JavaEE】_网络通信原理

目录 1. 网络发展史 2. 网络通信基础 1.1 IP地址 1.2 端口号 1.3 协议 1.3.1 概念 1.3.2 五元组 1.4 协议分层 1.4.1 协议分层的优点 1.4.2 协议分层的分类 1.4.3网络设备所在分层 1.4.4 两台主机通过TCP/IP协议通讯过程 1.5 封装与分用 1.5.1 封装 1.5.2 分用…

Docker 容器连接

Docker 容器连接 前面我们实现了通过网络端口来访问运行在 docker 容器内的服务。 容器中可以运行一些网络应用&#xff0c;要让外部也可以访问这些应用&#xff0c;可以通过 -P 或 -p 参数来指定端口映射。 下面我们来实现通过端口连接到一个 docker 容器。 网络端口映射 …

OpenCV-Python(46):基于KNN的手写数字OCR识别

目标 根据掌握的kNN 知识创建一个基本的OCR 程序使用OpenCV自带的手写数字和字母数据测试我们的程序 手写数字的OCR 我们的目的是创建一个可以对手写数字进行识别的程序。为了达到这个目的我们需要训练数据和测试数据。OpenCV安装包中有一副图片(/samples/ python2/data/digi…

使用java模拟兰顿蚂蚁

兰顿蚂蚁是一个经典的计算机科学问题&#xff0c;它模拟了一只蚂蚁在一个无限大的网格上移动的行为。下面是一个使用Java模拟兰顿蚂蚁的示例代码&#xff1a; public class LangtonAnt {private int[][] grid;private int antX;private int antY;private int antDirection; //…