Codeforces Round 930 (Div. 2)题解

A. Shuffle Party(Problem - A - Codeforces)

题目大意:给定一个n长数组,并使得a[i]=i,现在定义一种操作swap(k):找出k的最大不等于自己的除数d,交换a[k]和a[d],k从1开始直到n结束,问最后结束的时候1在哪里。

思路:这题的交换看似比较混乱,但是我们如果只盯着1的位置就会发现规律。1可以换到位置2,而位置2只能换到位置4,位置4换到位置8,...,所以实际上我们只要找到n在二进制下最高位1即可。

n在1e9的范围内,我们可以从30开始循环,往低位找。(注意int的数据范围在2^31-1的范围内,所以也就是说int类型的数最多31位,如果从32开始循环就会出现错误)

有两个二进制处理:

获取n的第i位是否是1,判断n>>i&1是否为1,如果为1,就说明n的第i位为1,否则就是0.
将最高位1后面的全部换成0:n>>i<<i,假设n的最高位1在第i位。

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n;
		scanf("%d",&n);
		int flag=1;
		for(int i=30;i>=0;i--)
		{
			if(n>>i&1) 
			{
				flag=n>>i<<i;
				break;
			}
		}
		printf("%d\n",flag);
	}
}

 B. Binary Path(Problem - B - Codeforces)

题目大意:现在有一个2行m列的方格阵,每个格子中的值是0或1,我们要从(1,1)到(2,n),每次只能向右或者向下移动一格,问字典序最小的移动方案数。

思路:这题我第一反应就是数字三角形模型+背包问题统计方案数,但也正是因为这个走入了误区,因为很显然这里是每个格子是不能将其中的数视为权重的,如果将0和1视为权重,那么就会出现两种字典序不同的方案最后的花费相同,很显然不符合题意,但是由于我没有跳出第一映像重新分析,就非得找到一个合适的dp的方法,绕来绕去最后实在没辙跑去看第三题了,浪费了不少时间,最后写出来的时候没卡上点。

这题和一般的dp问题不同,因为只能向右或者向下走,所以一旦向下走了就只能向右走了,剩下的步数就只有一种选择了,所以问题的核心在于什么时候向下走。

当我们还在上面的时候,每一步实际面临两种选择,一种是向右走,一种是向下走,字典序相同的时候方案不同那么我们看一下为什么会出现这种情况:

如图,如果三条路径对应的字典序相同,那么标号相同的位置的值必须相同。所以实际上我们只需要找出这样的一段区间即可。那么该怎么找呢,我们可以直接比较这样的格子,也可以比较上面一行向右和向下对应的两个格子是否相等。这里采用第二种方法,因为对输出序列友好一些,然后我们来看具体如何统计:

如果两步操作对应的格子的数是一样的,那么实际上是无所谓的,如果右边是0,下面是1,那么必须向右,前面已经统计的向右向下相等的位置的数目必须作废,如果右边是1,下面是0,那么必须向下,后面的讨论也就没有意义了。所以实际上我们只用一格一格往后找,当向右向下相同的时候计一下数,当两者不同,向右为0的时候重新计数,向下为0的时候直接退出。然后还有一点需要考虑,我们需要输出最后的序列,所以还要统计相等的那一段区间。

#include<bits/stdc++.h>
using namespace std;
char s[3][200010];
int dp[3][200010];
int n;
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		for(int i=1;i<=2;i++) scanf("%s",s[i]+1);
		int c=0,i,l=0,r=0;
		for(i=1;i<n;i++)
		{
			if(s[1][i+1]==s[2][i]) c++,r++;
			else if(s[1][i+1]>s[2][i]) break;
			else c=0,r=l=i+1;

		}
		if(i<=n)
		{
			for(int j=1;j<=i;j++) printf("%c",s[1][j]);
			for(int j=i;j<=n;j++) printf("%c",s[2][j]);
		}
		else
		{
			printf("%s",s[1]+1);
			printf("%c",s[2][n]);
		}
		printf("\n%d\n",c+1);
	}
}

C. Bitwise Operation Wizard(Problem - C - Codeforces)

题目大意:这题是交互题,实际上想让我们实现的是,通过询问若干次a|b与c|d的大小,进而找出异或值最大的两个数。

思路:这题也是我最开始的分析太过片面了,我只考虑了高位1,两个数的异或值大就说明两个数高位是不同的,a|b>c|d,就说明我们可以从a,b中选一个实际生效的数,从c,d中选一个没在|运算高位1中生效的数,然后就此推断出找出最大值和最小值进行异或,但是我忽略了1111111101,01,10这种情况。这种情况下显然选01不如选10。那么这道题该如何考虑呢?

我们还是想办法从这道题的特殊的地方入手,题目中给的数组是一个排列,从0到n-1的排列,那么最大的数显然是n-1,然后要找出n-1为0的哪些位置为1的数,显然两者进行|运算的值应该最大,但是如果仅仅是找或运算的话,那么n-1为1的位置,且找到的数对应位置也为1的位置的那种值如何排除呢,显然我们的目标值中1的个数最少,目标值为1的位置所有找到的值对应的位置应该也是1,但是应该比目标值大。所以就要找到所以值中最小的一个。比较两个数的大小可以通过询问a,a,b,b来得到。

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n;
		scanf("%d",&n);
		if(n==2)
		{
			printf("! 0 1\n"),fflush(stdout);
		}
		else
		{
			char op[2];
			int mx=0,mi=0;
			//找最大值
			for(int i=1;i<n;i++)
			{
				printf("? %d %d %d %d\n",mx,mx,i,i),fflush(stdout);
				scanf("%s",op);
				if(op[0]=='<') mx=i; 
			}
			for(int i=1;i<n;i++)
			{
				printf("? %d %d %d %d\n",mx,mi,mx,i),fflush(stdout);
				scanf("%s",op);
				if(op[0]=='<') mi=i;
				else if(op[0]=='=') 
				{
					printf("? %d %d %d %d\n",mi,mi,i,i),fflush(stdout);
					scanf("%s",op);
					if(op[0]=='>') mi=i;
				} 
			}
			printf("! %d %d\n",mx,mi),fflush(stdout);
		}
	}
}

D. Pinball(Problem - D - Codeforces)

题目大意:有一排格子,每个格子中只有'<'和'>'两种字符,有一个小球被放入了第i个格子,如果格子中是'<'那么小球下一秒就会往左移动一格,同时当前格子的字符变成'>',另一种字符同理,问小球放在每个格子的时候离开格子需要多少秒。(1<=n<=5e5)

思路:如果可以模拟的话显然这题不太难,但是n的数据范围太大了,而且还有多组测试样例,很显然不能通过模拟来写,那么就要找一下规律了。

我们先只来看相邻的两个格子,而且将小球放在第一个格子处,

如果是>>,直接向右两步

如果是<<,直接向左一步

如果是><,向右一步,向左两步

如果是<>,直接向左一步。

很显然对于同向的格子可以一直沿着这个方向往前,对于反向的格子>>>><,第一次走到反向位置时,会发现已经变成了<<<<<,所以又可以一直往左。

><<<>>><

>>>>>>><

<<<<<<<<

<<<>>><

抽象一下,如果走到反向位置后,相当于可以将反向位置同化,最后至少有一端是全部被同向化了。起始方向的方向需要统计反向的个数,起始反向的方向需要统计同向个数

统计位置和(下标和处理一下)与个数

两个方向都统计一下

如果是>的话,那么要么左右阻碍个数相同,从右边出,要么左边的阻碍比右边少1个,从左边出

如果是<的话,要么左右阻碍个数相同,从左边出,要么右边的阻碍比左边少1个,从右边出

多余的阻碍可以不用考虑。

>:

cntl[i]>=cntr[i]:左右各考虑最近的cntr[i]个阻碍

cntl[i]<cntr[i]:左边考虑cntl[i]个阻碍,右边考虑最近的cntl[i]+1个阻碍

<:

cntl[i]<=cntr[i]:左右各考虑最近的cntl[i]个阻碍

cntl[i]>cntr[i]:右边考虑cntr[i]个阻碍,左边考虑最近的cntr[i]+1个阻碍,

倒是可以用单调队列统计,

看上去要实现对应位置的查找很麻烦,但实际上我们可以用前缀和+二分的思想来实现。

尽管如此细节处理还是很麻烦。

#include<bits/stdc++.h>
using namespace std;
#define int long long
char s[500010];
int l[500010],r[500010];
int cntl[500010],cntr[500010];
signed main()
{
	int t;
	scanf("%lld",&t);
	while(t--)
	{
		int n;
		scanf("%lld",&n);
		scanf("%s",s+1);
		for(int i=1;i<=n;i++)
		{
			if(s[i]=='>')
			{
				cntl[i]=cntl[i-1],cntr[i]=cntr[i-1]+1;
				l[i]=l[i-1],r[i]=r[i-1]+i;
			}
			else//<
			{
				cntl[i]=cntl[i-1]+1,cntr[i]=cntr[i-1];
				l[i]=l[i-1]+i,r[i]=r[i-1];
			}
		}
		int ans;
		for(int i=1;i<=n;i++)
		{
			if(s[i]=='>')
			{
				//右边的<     左边的> 
				if(cntl[n]-cntl[i]<=cntr[i-1])//从右边出,那么左边的>不会用完
				{
					//找到左边第cntl[n]-cntl[i]个>
					int x=cntl[n]-cntl[i];
					int xl=1,xr=i-1,p=xl;
					if(x==0) p=i;//这里会出现为0的情况
					else
					{
						while(xl<xr)
						{
							int mid=(xl+xr)/2;
							if(cntr[i-1]-cntr[mid-1]<x) xr=mid-1;
							else if(cntr[i-1]-cntr[mid-1]>x) xl=mid+1;
							else xl=xr=mid;
						}
						p=xl;
					}
					//[mid,i-1]这个区间中的>
					ans=2*(l[n]-l[i]-x*i) + 2*(x*i-(r[i-1]-r[p-1])) + (n-i+1);
				}
				else//从左边出,需要获得右边第cntr[i-1]+1个<的位置
				{
					int x=cntr[i-1]+1;
					int xl=i+1,xr=n,p=xl;
					while(xl<xr)
					{
						int mid=(xl+xr)/2;
						if(cntl[mid]-cntl[i]<x) xl=mid+1;
						else if(cntl[mid]-cntl[i]>x) xr=mid-1;
						else p=xl=xr=mid;
					}
					p=xl;
					ans = 2*(i*cntr[i-1]-r[i-1])+2*(l[p]-l[i]-(cntl[p]-cntl[i])*i)+i;
				}
			}
			//><<
			else//<
			{
				//左边的> 右边的<
				if(cntr[i]<=cntl[n]-cntl[i])//从左边出
				{
					//获取右边第cntr[i]个<的位置
					int x=cntr[i];
					int xl=i,xr=n,p=xl;
					while(xl<xr)
					{
						int mid=(xl+xr)/2;
						if(cntl[mid]-cntl[i]<x) xl=mid+1;
						else if(cntl[mid]-cntl[i]>x) xr=mid-1;
						else p=xl=xr=mid;
					}
					p=xl;
					ans=2*(x*i-r[i])+2*(l[p]-l[i]-x*i)+i;
				}
				else//从右边出,这里不会出现某种值为0的情况
				{
					//找左边第cntl[n]-cntl[i]个>的位置
					int x=cntl[n]-cntl[i]+1;
					int xl=1,xr=i-1,p=xl;
					while(xl<xr)
					{
						int mid=(xl+xr)/2;
						if(cntr[i-1]-cntr[mid-1]<x) xr=mid-1;
						else if(cntr[i-1]-cntr[mid-1]>x) xl=mid+1;
						else p=xl=xr=mid;
					}
					p=xl;
					ans = 2*(x*i-(r[i-1]-r[p-1]))+2*(l[n]-l[i]-i*(x-1))+n-i+1;
				}
			}
			printf("%lld ",ans);
		}
		printf("\n");
	}
}

总结:b,c两道题都给了一个启示,看到题目先从普遍的情况去思考,当卡住的时候,不要咬死不放,想办法从这道题目特殊的地方再去思考一下。d题的启示在于从某个范围中紧邻的第x个符合要求的数的时候可以考虑前缀和+二分来实现。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

训练1 : 老头

以前用blender做的特效 总结 头发很费时间, 需要参考和练习眼窝周边结构还有些待准确把握从光与影中揣摩轮廓形状 从少量面掌握大体, 从多数面雕刻细节

云时代【5】—— LXC 与 容器

云时代【5】—— LXC 与 容器 三、LXC&#xff08;一&#xff09;基本介绍&#xff08;二&#xff09;相关 Linux 指令实战&#xff1a;使用 LXC 操作容器 四、Docker&#xff08;一&#xff09;删除、安装、配置&#xff08;二&#xff09;镜像仓库1. 分类2. 相关指令&#xf…

教师招聘和事业编d类有什么区别吗

每年都有大批怀揣教育梦想的年轻人&#xff0c;站在职业的十字路口&#xff0c;对未来充满期许与疑惑。他们中的许多人都会面临这样一个问题&#xff1a;教师招聘和事业编D类&#xff0c;到底有什么区别&#xff1f;今天&#xff0c;就让我来为你揭开这两者的神秘面纱。 别被这…

基于session注册JAva篇springboot

springboot3全家桶&#xff0c;数据库 &#xff1a;redis&#xff0c;mysql 背景环境&#xff1a;邮箱验证码&#xff0c;验证注册 流程&#xff1a;先通过邮箱验证&#xff0c;发送验证码&#xff0c;将获取到的session和验证码&#xff0c;存入redis里&#xff08;发送邮箱…

3d模型版本转换器注意事项---模大狮模型网

在使用3D模型版本转换器时&#xff0c;有一些注意事项可以帮助您顺利完成模型转换并避免不必要的问题&#xff1a; 数据完整性&#xff1a;在进行模型转换之前&#xff0c;确保您的原始3D模型文件没有损坏或缺失数据。损坏的文件可能导致转换器无法正常处理或输出错误的结果。 …

【前端素材】推荐优质在线大气数码商城电商网页ClassiList平台模板(附源码)

一、需求分析 1、系统定义 电子数码电商平台是专门销售电子数码产品&#xff08;如手机、电脑、相机、智能设备等&#xff09;的在线电子商务平台。这些平台提供了一个便捷的购物环境&#xff0c;让消费者可以方便地浏览、比较和购买各种电子数码产品。 2、功能需求 在线大…

常见外设学习以及无线通信频率

常见外设 UART UART&#xff08;Universal Asynchronous Receiver/Transmitter&#xff0c;通用异步收发器&#xff09;是一种异步、串行、全双工的通信总线。 UART 有3根线&#xff0c;分别是&#xff1a;发送线&#xff08;TX&#xff09;、接收线&#xff08;RX&#xff…

找不到msvcp140.dll无法运行程序如何处理?分享5种解决方法

在计算机系统运行过程中&#xff0c;如果无法找到必要的动态链接库文件msvcp140.dll&#xff0c;可能会引发一系列的问题与故障。这个特定的dll文件是Microsoft Visual C Redistributable Package的一部分&#xff0c;对于许多基于此编译环境开发的应用程序至关重要。缺失msvcp…

Android WebView访问网页+自动播放视频+自动全屏+切换横屏

一、引言 近期&#xff0c;我发现电视家、火星直播等在线看电视直播的软件都已倒闭&#xff0c;而我奶奶也再无法通过这些平台看电视了。她已六十多岁&#xff0c;快七十岁啦。这些平台的倒下对我来说其实没有多大的影响&#xff0c;但是对于文化不多的她而言&#xff0c;生活中…

【力扣白嫖日记】550.游戏玩法分析IV

前言 练习sql语句&#xff0c;所有题目来自于力扣&#xff08;https://leetcode.cn/problemset/database/&#xff09;的免费数据库练习题。 今日题目&#xff1a; 550.游戏玩法分析IV 表&#xff1a;Activity 列名类型player_idintdevice_idintevent_datedategames_played…

探秘Python的Pipeline魔法

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站AI学习网站。 目录 前言 什么是Pipeline&#xff1f; Pipeline的基本用法 Pipeline的高级用法 1. 动态调参 2. 并行处理 3. 多输出 …

模型练习史

文章目录 肌肉光头vikingtorso死侍蓝毒液卡通girlwalletdog headman anatomy总结 肌肉光头 viking torso 死侍 蓝毒液 卡通girl wallet dog head man anatomy 总结 zbrush 与 blender 结合使用, 善 !

SpringBoot+Vue实战:打造企业级项目管理神器

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

Python多功能课堂点名器、抽签工具

一、问题缘起 去年&#xff0c;ChatGPT浪潮袭来&#xff0c;我懂简单的Python基础语法&#xff0c;又有一些点子&#xff0c;于是借助于人工智能问答工具&#xff0c;一步一步地制作了一个点名器&#xff0c;也可以用于抽签。当时&#xff0c;我已经设计好页面和基础的功能&am…

mock工具whistle使用笔记

1、下载安装地址&#xff1a;关于whistle GitBook 安装完后&#xff0c;用本地的ip&#xff1a;设置的端口就可以反问&#xff0c;端口默认的8899&#xff0c;可以自定义 2、抓包https&#xff1a; &#xff08;1&#xff09;打开https &#xff08;2&#xff09;下载证书&…

【王道数据结构】【chapter8排序】【P371t5】

编写一个算法&#xff0c;在基于单链表表示的待排序关键字序列上进行简单选择排序 #include <iostream> #include <time.h> #include <stdlib.h> typedef struct node{int data;struct node *next; }node,*pnode;pnode buynode(int x) {pnode tmp(pnode) mal…

【JVM】聊聊常见的JVM排查工具

JDK工具包 jps 虚拟机进程状况工具 jps是虚拟机进程状况工具&#xff0c;列出正在运行的虚拟机进程&#xff0c;使用 Windows 的任务管理器或 UNIX 的 ps 命令也可以查询&#xff0c;但如果同时启动多个进程&#xff0c;必须依赖 jps。jps -l 显示类名 jps :列出Java程序进程…

【Python】成功解决ValueError: not enough values to unpack (expected 2, got 1)

【Python】成功解决ValueError: not enough values to unpack (expected 2, got 1) &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&am…

第40期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以找…

仿牛客网项目---私信列表和发送列表功能的实现

这篇文章我们来讲一下我的这个项目的另外一个功能&#xff1a;私信列表和发送列表功能。 先来设计DAO层。 Mapper public interface MessageMapper {// 查询当前用户的会话列表,针对每个会话只返回一条最新的私信.List<Message> selectConversations(int userId, int of…