2021统一省选 A卷 day1解析

2024-05-11 00:58
文章标签 统一 解析 2021 day1 省选

本文主要是介绍2021统一省选 A卷 day1解析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题面,就参照洛谷的吧。

  1. 卡牌游戏
  2. 矩阵游戏
  3. 图函数

重点看思维过程。

卡牌游戏

  1. 爆搜的话,过前两个点没问题。枚举要翻牌的数量m,然后从n张中翻m张,直接统计最大最小值。

  2. 考虑到卡牌是按照正面数值由小到大排序的,设c[]数组,将a[]和b[]存入c[],然后由小到大排序。枚举最小值minn为c[i],最大值maxn为c[j],这两个值是不可更改的,现在转为判定性问题,注意minn和maxn不能是同一张牌的,要判别一下。那么正面数值在这个区域的,是不用翻牌的。对于正面数据a[]来说,假设最小值minn的下标为i,最大值maxn的下标为j。如下:
    在这里插入图片描述
    那么区间[i,j]是不需要翻牌的。区间[1,i-1]和[j+1,n]是需要翻牌的。最后看确定的最小值和最大值的下标是否在翻牌区域,如果不在翻牌区域,需要m减1或者减2,有几个不在翻牌区域,就减几个。然后只要满足:翻牌数量小于等于m和翻牌区间的最值在minn和maxn之间,就是合法解。。用ST算法维护区间最大值和区间最小值即可。整体复杂度是O(n^2)的。可以过前4个点。

  3. 以上思路稍加调整就可以过第5~6个点。虽然n值较大,达到了5e5,但是m值最大1000。因此枚举的时候,直接枚举前半段翻牌的长度为x,则后半段翻牌的长度最大为m-x。其余同思路2。整体复杂度是O(m^2)。

  4. 为了加速上述的判定,可以用二分法,就是二分答案。这个题目的答案具有单调性,可以转为判定性问题。假设极值为x,现在假定最小值为minn,那么最大值maxn为minn+x。最大和最小值都得是卡牌上的数值。ai值小于minn的部分需要翻牌,而且得保证翻出的牌的最值在minn和maxn之间,ai值大于maxn的也需要翻牌,而且得保证翻出的牌的最值在minn和maxn之间。否则,这组不满足,跳过。
    如何确定最小值minn呢?需要正面和反面的数值一起,设数组c[],依次存入a[]和b[],然后排序,由小到大,需要记下c[]中的数据在原先数列中的下标。用map就可以。因为2n个数据都不相同,所以不矛盾。在c[]中依次枚举作为最小值。最后看确定的最小值和最大值的下标是否在翻牌区域,如果不在翻牌区域,需要m减1或者减2,有几个不在翻牌区域,就减几个。然后只要满足:翻牌数量小于等于m和翻牌区间的最值在minn和maxn之间,就是合法解。枚举时复杂度O(n),查询最值O(logn),共二分次数O(logn),整体复杂度为O(lognnlogn)。可以过全部点。

矩阵游戏

发现由 b i , j b_{i,j} bi,j倒推出 a i , j a_{i,j} ai,j有很多种方法。比如:对于b[1][1],a[1][1]=a[1][2]=a[2][1]=b[1][1]/4,a[2][2]=b[1][1]/4+b[1][1]%4。其他的位置填的话,只需要再确定两个值就可以了,一个值可以填b[][]/2,另一个值填b[][]/2+b[][]%2。这样倒推出来的是没有限制的a[][]。注意限制是:a[i][j]>=0&&a[i][j]<=1e6。我们发现对于某一列,如果从上到下依次加减相同的值,不影响正确性。比如:+x,-x,+x,-x,……,也可以从减开始,比如:-x,+x,-x,+x,……。对于某一行,也是这样。

下面的问题就是如何由得到的一个随机矩阵,通过某种方法转化为合法矩阵。

对于n,m<=3和m=2的情况,感觉应该可以暴力过,但是想不到好的方法。因为按照上面的思路,如何将随机矩阵转化为合法矩阵,总要用到差分约束,也不是暴力做法。直接考虑全部数据规模。

对于奇数行,在行上的改变从加开始,对于偶数行,从减开始。

对于奇数列,在列上的变化从减开始,对于偶数列,从加开始。

在这里插入图片描述
对于某个位置,要经过行上的和列上的变化。这些变化要同时满足所有位置,得列不等式方程组。比如对于(1,1),需要满足: a [ 1 ] [ 1 ] + x 1 − y 1 > = 0 a[1][1]+x1-y1 >= 0 a[1][1]+x1y1>=0 && a [ 1 ] [ 1 ] + x 1 − y 1 < = 1 e 6 a[1][1]+x1-y1 <= 1e6 a[1][1]+x1y1<=1e6。所有的位置都要满足上述类似的要求。

这就最终能化成类似这样的不等式:a<=x1-x2<=b,这个不等式可以拆成:x1<=x2+b和x2<=x1+(-a)。典型的差分约束系统,用最短路解就可以了。总共是n+m个点,n*m条边。spfa可以过。

图函数

几乎每次大考中都会有这种重新定义的题目,一般比较绕,但是跟着样例模拟一遍,就能大致明白它的套路。

n<=10的前4个点,可以直接模拟过。判断两个点是否连通,可以用dfs搜。链式前向星存图,用vis[]对每条边打标记,删除某条边,就是vis置为0。

以下有点长,但不难理解,耐心阅读。

再具体考虑。对于图G,对于点u,判断点v是否能和点u构成点对,那么点v应该满足什么条件呢?首先要明确的是点u和点u能构成点对,然后消去自身,因此v<u。v->u和u->v之间的点满足什么条件呢?之间的点都是>v的。假设v->u和u->v之间存在点x,而且x<=v。那么x->u和u->x之间也是连通的,这样x及其边要被消去,因此等到枚举到v时,x已经不存在了。假设矛盾。

明白这一点的话,也就没必要真正地删除边了,只需要做一些转换。对于任意的图G,有两点v和u,v<u,如果v->u和u->v之间的点都是>v的,那么u和v构成点对。本题求的分别是原图G的点对数,删除一条边的点对数,删除两条边的点对数,……,删除m条边的点对数。真的要一个图一个图的去求吗?肯定不会。应该能想到,这些m+1个图,会有某种连续性。

假设上述对应的图分别为G0,G1,G2,……,Gm。有两点v和u,v<u。v->u和u->v某条路径上的边的最小值为i,也就是说v->u和u->v的路径至少会到删除第i次边的时候才会被破坏。也就是说点u和v,对于图G0,G1,G2,……,Gi都是点对。v和u之间双联通的路径会只有一条吗?也许不会,所以要求出v和u之间所有路径边的最小值的最大值。因为我们希望u和v能产生更多的贡献,所以要最大值。设数组f[i][j]用来记录合法点对i和j之间的边的编号的最小值的最大值,那么上述u和v对答案的贡献就可以用min(f[u][v],f[v][u])来表示。

设数组g[i]表示第i条边对其前面的图的贡献,前面的图指的是:G0,G1,……,Gi-1。想求第i个图总共有多少点对,只要求出第i条边后面的边对它的贡献即可,也就是后缀和。

现在难点就是如何求这个f[i][j]?可以用floyed。首先要明白:对于floyed,在最外层循环到k时,dis[i][j]最短路径上除了i和j两点,路径上的其他结点编号都小于等于k。我们在学习最小环问题的时候讨论过这个问题。

在这里插入图片描述
以下是最小环问题的算法。

在这里插入图片描述
我们要计算f[i][j],假设i<j,要求是i->j和j->i之间的点都是>j的,如何保证在floyed的过程中f[i][j]的点满足这个条件?只要将松弛点k从大到小枚举就搞定了!这样在做到f[i][j]时,上面的点除了i和j外都是大于j的。

可参考以下代码,1000的规模的floyed开o2,居然能过。

#include<cstdio>
using namespace std;
int n,m,x,y,f[1010][1010],g[200010],ans[200010];
inline int min(int x,int y){return x<y?x:y;}
inline int max(int x,int y){return x>y?x:y;}
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=m;i++) scanf("%d%d",&x,&y),f[x][y]=i; for(int k=n;k>=1;k--)for(int i=1;i<=n;i++)if(f[i][k]){if (i>k){for(int j=1;j<k;j++)f[i][j]=max(f[i][j],min(f[i][k],f[k][j]));}else{for(int j=1;j<=n;j++) f[i][j]=max(f[i][j],min(f[i][k],f[k][j]));}}for (int i=1;i<=n;i++)for (int j=i+1;j<=n;j++)g[min(f[i][j],f[j][i])]++;ans[m+1]=n;for(int i=m;i>=1;i--)ans[i]=ans[i+1]+g[i];for(int i=1;i<=m+1;i++)printf("%d ",ans[i]);return 0;
}

备注:代码转载自洛谷“永恒之眼”的博客。

这篇关于2021统一省选 A卷 day1解析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/978063

相关文章

使用Java解析JSON数据并提取特定字段的实现步骤(以提取mailNo为例)

《使用Java解析JSON数据并提取特定字段的实现步骤(以提取mailNo为例)》在现代软件开发中,处理JSON数据是一项非常常见的任务,无论是从API接口获取数据,还是将数据存储为JSON格式,解析... 目录1. 背景介绍1.1 jsON简介1.2 实际案例2. 准备工作2.1 环境搭建2.1.1 添加

在C#中合并和解析相对路径方式

《在C#中合并和解析相对路径方式》Path类提供了几个用于操作文件路径的静态方法,其中包括Combine方法和GetFullPath方法,Combine方法将两个路径合并在一起,但不会解析包含相对元素... 目录C#合并和解析相对路径System.IO.Path类幸运的是总结C#合并和解析相对路径对于 C

Java解析JSON的六种方案

《Java解析JSON的六种方案》这篇文章介绍了6种JSON解析方案,包括Jackson、Gson、FastJSON、JsonPath、、手动解析,分别阐述了它们的功能特点、代码示例、高级功能、优缺点... 目录前言1. 使用 Jackson:业界标配功能特点代码示例高级功能优缺点2. 使用 Gson:轻量

Java如何接收并解析HL7协议数据

《Java如何接收并解析HL7协议数据》文章主要介绍了HL7协议及其在医疗行业中的应用,详细描述了如何配置环境、接收和解析数据,以及与前端进行交互的实现方法,文章还分享了使用7Edit工具进行调试的经... 目录一、前言二、正文1、环境配置2、数据接收:HL7Monitor3、数据解析:HL7Busines

python解析HTML并提取span标签中的文本

《python解析HTML并提取span标签中的文本》在网页开发和数据抓取过程中,我们经常需要从HTML页面中提取信息,尤其是span元素中的文本,span标签是一个行内元素,通常用于包装一小段文本或... 目录一、安装相关依赖二、html 页面结构三、使用 BeautifulSoup javascript

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

OWASP十大安全漏洞解析

OWASP(开放式Web应用程序安全项目)发布的“十大安全漏洞”列表是Web应用程序安全领域的权威指南,它总结了Web应用程序中最常见、最危险的安全隐患。以下是对OWASP十大安全漏洞的详细解析: 1. 注入漏洞(Injection) 描述:攻击者通过在应用程序的输入数据中插入恶意代码,从而控制应用程序的行为。常见的注入类型包括SQL注入、OS命令注入、LDAP注入等。 影响:可能导致数据泄

从状态管理到性能优化:全面解析 Android Compose

文章目录 引言一、Android Compose基本概念1.1 什么是Android Compose?1.2 Compose的优势1.3 如何在项目中使用Compose 二、Compose中的状态管理2.1 状态管理的重要性2.2 Compose中的状态和数据流2.3 使用State和MutableState处理状态2.4 通过ViewModel进行状态管理 三、Compose中的列表和滚动

Spring 源码解读:自定义实现Bean定义的注册与解析

引言 在Spring框架中,Bean的注册与解析是整个依赖注入流程的核心步骤。通过Bean定义,Spring容器知道如何创建、配置和管理每个Bean实例。本篇文章将通过实现一个简化版的Bean定义注册与解析机制,帮助你理解Spring框架背后的设计逻辑。我们还将对比Spring中的BeanDefinition和BeanDefinitionRegistry,以全面掌握Bean注册和解析的核心原理。