当前位置: 首页 > news >正文

速通ACM省铜第二天 赋源码(Adjacent XOR和Arboris Contractio)

目录

引言:

Adjacent XOR

        题意分析

        逻辑梳理

        代码实现

Arboris Contractio

        题意分析

        逻辑梳理

        代码实现

结语:


引言:

        本来今天也是打算讲一道题的,但是因为第一道的1400的题感觉有点过于简单了,感觉没有1400的题的感觉,于是就决定这篇讲俩题,而且好巧不巧,这俩题竟然是在同一场div3里的,而且更神奇的是,E题开出来的人竟然比D题还多,如图

        但确实,我打下来也感觉D题比E题难打一点,那么接下来,我们就开始进行题目的讲解————>

                ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        


Adjacent XOR

        那么,我们先来讲相对另一道而言总体偏简单的题目,我们先来分析一下题目

        题意分析

        这是题目链接Problem - 2131E - Codeforces

        不想跳转可看下图

        首先,我们来看题目,这个题目的描述十分的简单,就是给你一个数组a,然后问你能不能把这个数组a变成数组b

        然后操作也很简单,就是可以随便选择下标(需要没被选择过的),然后对该下标和相邻的下一个下标的俩个值进行异或

        题目的意思就这么简单,那么我们来将题目的要求进行逻辑梳理一番


        逻辑梳理

        首先,题目问我们a能不能转换成b,最简单的一个判断方式就是判断这俩个数组的最末尾元素是否一样,若不一样,则输出“NO”,若一样,再进行讨论,为什么呢,我们来结合我画的图进行分析

        根据题意,a数组的变化,撑死只能将最末尾的i与i+1进行变化,但这样变化后得到的新元素的位置也在i位,但是这种已经是最靠后的变化方式了,所以,我们可知,a数组的最后一位,是无法变化的,所以如果a跟b数组的末尾元素不一样,那么,a就不能转换为b

        那么若a与b数组的末尾元素是一样的,接下来,我们来进行下一步的分析

        首先,如果我们判断能否将a[i]变化成b[i],我们可以有俩种方式,一种是a[i]与b[i]是否一样,另一种是a[i]异或a[i+1]后是否与b[i]一样,不管是哪种情况,i 位置的能否转换都不会被 i 前面a数组的元素所影响,所以我们可以思考倒推,因为只有后面的元素可以对a[i]产生影响

        因为题目告诉了我们,选择异或的顺序是可以任意的,所以当选择 i 这个位置进行判断时,会有三种情况

        1.a[i]是否等于b[i]

        2.a[i]^a[i+1]是否等于b[i]

        3.a[i]^b[i+1]是否等于b[i]

        只有这三个条件都无法满足时,才会输出“NO”,那么我们具体来讲解下这三种情况

        第一种情况很简单,相等的话不用操作就是符合的,很简单

        第二种情况也很简单,就是 i+1 下标上的元素并没有选择进行异或,先对下标为 i 的位置进行异或,若等于,就可以变化(因为 i 在 i+1 前,所以 i+1 之后想要变化时候也不会被 i 的变化所影响)

        第三种情况也好想,b[i+1]表示的是a[i+1]已经被进行异或过了,然后通过i与已经被异或过的i+1进行异或,若可以变化,则可以实现目的

        所以,只有这三种情况都不满足时,才会使a数组无法变成b数组

        那么,这个题目的思路已经理清楚了,那么代码也自然就很简单了,那么接下来,我们来写代码


        代码实现

        这个题主要是逻辑难想,逻辑想通了代码其实很简单,那么,这边就直接放AC的代码了

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <queue>
using namespace std;int t, n;
long long a[200010];
long long b[200010];int main()
{cin >> t;while (t--){cin >> n;for (int i = 1; i <= n; i++)cin >> a[i];for (int i = 1; i<=n; i++)cin >> b[i];if (a[n] != b[n]){cout << "No" << endl;continue;}int xixi = 1;int j = n - 1;while (j){if (a[j] != b[j] && b[j] != (a[j] ^ b[j + 1]) && b[j] != (a[j] ^ a[j + 1])){xixi = 0;cout << "No" << endl;break;}j--;}if (xixi)cout << "Yes" << endl;}return 0;
}

        那么,这题就讲到这里结束啦,希望你们有所收获

        接下来,我们来讲下一道题,下一道题跟上一道题刚好相反,思路好想,但是代码比较难实现


Arboris Contractio

        那么,我们先来分析一下题目

        题意分析

        这是题目链接Problem - 2131D - Codeforces

        不想跳转可看下图

        这题目相比上一题看着挺长的,但其实问的也很简单,就是题目会给你一个无环数,然后通过一系列的方法,将那颗无环树的深度变为2,然后问你最少的操作次数是几次,就没了

        然后一次操作分为三步走,就是选一条路,然后把那条路所有的点全部拆开,然后再将后面的点全部跟头的那个点连上,就是一次操作

        那么接下来,我们进行逻辑分析


        逻辑梳理

        逻辑其实很好梳理,首先,对于每个点的最少操作次数只需要数该节点深度不为1的分支有几条,分支的结果就是他需要操作的最小次数(这个自己理会,应该是很好理解的),然后通过一个个的对比,找出操作次数最少的一个节点,然后输出即可

        思路是很清晰的,但是明显,这个思路是完全不可能实现的,因为若要实现这个思路,首先每个节点都要访问一遍,每次访问不同节点的时候,其他节点对于该节点的深度也会发生变化,而且每个节点的分支也不同,极多的不可控因素会使得这个思路完全无法转换成代码来实现,这也是困住了我挺久的地方

        所以我们需要通过原先的思路,来创造出一个能转换成代码的思路

        那么,既然是分支,我们就可以思考到叶子节点,因为每个点的分支,肯定最后都会抵达叶子节点,所以我们可以先算出这颗树总共有多少个叶子结点,然后一个循环,遍历完所有的点,每次遍历一个点的时候,可以将叶子节点的总数减去该节点已经有的深度为1的叶子节点的个数,这样得到的值便是该点的最少操作次数,这么一来,是不是就比一开始的时候的方式便捷了许多

        :我们可以进行特判,即若只有俩个点,那输出便为0,因为2个点不管怎么连都已经是最小宽度了,根本不需要进行任何操作

        那么,逻辑梳理就梳理完了,接下来就进入代码实现部分


        代码实现

        在讲代码实现之前,特别注意,一定要把数组提到外面去,不然会导致栈溢出,切记,这点卡了我好久,结果发现原来是数组开在局部把栈区挤爆了(因为我一开始把数组放局部了,导致一运行就异常)那么,数组放在全局了,就不要忘了每次循环完进行清空操作

        除开这点,别的就很简单了,我们用vector来存储每个点所相连接的点,然后通过判断点的size来确定该点是不是叶子结点,因为叶子节点的size肯定为1

        然后我们想让总次数最少,只需要点的叶子结点最多即可,因为一个点的叶子节点越多,减去的值就越大,故而总次数越少

        那么,接下来,我们就来看AC代码

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <queue>
#include <vector>
using namespace std;int t, n;
vector<int> arr[200010];
void solv()
{int u, v;cin >> n;for (int i = 1; i < n; i++){cin >> u >> v;arr[u].push_back(v);arr[v].push_back(u);}if (n == 2){cout << "0" << endl;return;}int yesum = 0;for (int i = 1; i <= n; i++)if (arr[i].size() == 1)yesum++;int ye = 0;for (int i = 1; i <= n; i++){int Ye = 0;for (int j = 0; j < arr[i].size(); j++){if (arr[arr[i][j]].size() == 1)Ye++;}ye = max(ye, Ye);}cout << yesum - ye << endl;for (int i = 1; i <= n; i++){while (arr[i].size())arr[i].clear();}
}int main()
{cin >> t;while (t--){solv();}return 0;
}

那么,这题也讲完啦

结语:

        今日算法讲解到此结束啦,希望对你们有所帮助,谢谢观看,如果觉得不错可以分享给朋友哟


文章转载自:

http://frFicGPq.jmLLh.cn
http://1NphRpby.jmLLh.cn
http://r0oCSDyx.jmLLh.cn
http://vULbudtz.jmLLh.cn
http://uvA9iMky.jmLLh.cn
http://70rptR9O.jmLLh.cn
http://OKUIBg4i.jmLLh.cn
http://VSB6F97d.jmLLh.cn
http://1aImCwGa.jmLLh.cn
http://w3qVxDEP.jmLLh.cn
http://LbBcOZ0i.jmLLh.cn
http://bH7g3zxx.jmLLh.cn
http://BvLyF2fW.jmLLh.cn
http://msxgNmRV.jmLLh.cn
http://zQ4RZZji.jmLLh.cn
http://rwjrDPgY.jmLLh.cn
http://70WvO4NM.jmLLh.cn
http://c4oNEbPk.jmLLh.cn
http://NDyzPA8w.jmLLh.cn
http://KHY0fJUf.jmLLh.cn
http://bcZGq0xc.jmLLh.cn
http://QxZHU76D.jmLLh.cn
http://aHX2dJST.jmLLh.cn
http://hKbTOzGe.jmLLh.cn
http://MsRvDXWH.jmLLh.cn
http://qE5yyWql.jmLLh.cn
http://bNbyV0FK.jmLLh.cn
http://yQrhYo2z.jmLLh.cn
http://Xw7zztuz.jmLLh.cn
http://bGTfMLlx.jmLLh.cn
http://www.dtcms.com/a/380354.html

相关文章:

  • Python快速入门专业版(二十四):while循环:条件循环与“死循环”避免(猜数字游戏案例)
  • 神经网络构成框架-理论学习
  • 智能眼镜产品成熟度分析框架与评估
  • 从零学算法2327
  • 【C++】:list容器全面解析
  • 渲染农场多少钱一小时
  • IDEA试用过期,无法登录,重置方法
  • IP验证学习之case编写
  • 通过Dockerfile构建Docker镜像并训练模型
  • 操作系统内核架构深度解析:从微内核到宏内核的设计哲学与性能权衡
  • IIS运行账户设置记录
  • 服务管理 systemctl
  • HTTP与HTTPS
  • devextreme-vue表格设置可复制粘贴
  • Go 语言 PDF 生成库综合比较与实践指南
  • 图技术重塑金融未来:悦数图数据库如何驱动行业创新与风控变革
  • 金融数据---ETF日线行情数据
  • Vue 整体框架全面解析
  • 鸿蒙 NEXT应用国际化:时区与夏令时处理
  • 海外代理IP平台哪家好?高纯净度稳定住宅代理IP平台推荐
  • 锂电池行业生产中 AI 应用场景与价值分析
  • MySQL 命令行导入 SQL 文件
  • 3DMAX自动材质开关插件AutoMaterial安装和使用方法
  • Ubuntu C编程 (make工具和Makefile的引用)
  • 9.12AI简报丨腾讯投资AI游戏平台,B站开源AniSora V3
  • 家庭健康智能终端:解锁智能家居时代的健康管理
  • 机器视觉检测如何使用360 度全景成像镜头进行AI 瑕疵检测
  • # Windows驱动程序开发入门:从原理到实践
  • 在Webpack中集成Vite的开发服务器时,可能会遇到哪些兼容性问题?如何解决?
  • DCA1000 AWR1843 环境安装