cf Educational Codeforces Round 40 C. Matrix Walk

2024-03-24 07:58

本文主要是介绍cf Educational Codeforces Round 40 C. Matrix Walk,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原题:

C. Matrix Walk
time limit per test1 second
memory limit per test256 megabytes

inputstandard input
outputstandard output

There is a matrix A of size x × y filled with integers. For every , Ai, j = y(i - 1) + j. Obviously, every integer from [1..xy] occurs exactly once in this matrix.

You have traversed some path in this matrix. Your path can be described as a sequence of visited cells a1, a2, …, an denoting that you started in the cell containing the number a1, then moved to the cell with the number a2, and so on.

From the cell located in i-th line and j-th column (we denote this cell as (i, j)) you can move into one of the following cells:

(i + 1, j) — only if i < x;
(i, j + 1) — only if j < y;
(i - 1, j) — only if i > 1;
(i, j - 1) — only if j > 1.
Notice that making a move requires you to go to an adjacent cell. It is not allowed to stay in the same cell. You don’t know x and y exactly, but you have to find any possible values for these numbers such that you could start in the cell containing the integer a1, then move to the cell containing a2 (in one step), then move to the cell containing a3 (also in one step) and so on. Can you choose x and y so that they don’t contradict with your sequence of moves?

Input
The first line contains one integer number n (1 ≤ n ≤ 200000) — the number of cells you visited on your path (if some cell is visited twice, then it’s listed twice).

The second line contains n integers a1, a2, …, an (1 ≤ ai ≤ 109) — the integers in the cells on your path.

Output
If all possible values of x and y such that 1 ≤ x, y ≤ 109 contradict with the information about your path, print NO.

Otherwise, print YES in the first line, and in the second line print the values x and y such that your path was possible with such number of lines and columns in the matrix. Remember that they must be positive integers not exceeding 109.

Examples

input
8
1 2 3 6 9 8 5 2
output
YES
3 3

input
6
1 2 1 2 5 3
output
NO

input
2
1 10
output
YES
4 9

中文:
给你一个序列,x1,x2,x3…xn,让你找出一个X×Y的二维矩阵,这个二维矩阵的排列方式是1到X×Y的数字横向依次排列。
在这个矩阵当中,你可以从一个位置(i,j)向上、向下、向左、向右移动,在不超过边界的情况下,按照这个移动方式,能否找到实现最开始给定序列的一个路径(不允许在同一个位置停留)。如果存在这个矩阵,输出这个矩阵的行数和列数,否则输出NO

例如样例1
这里写图片描述

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;const ll row=1e9;
int n,a[200001],r,l,x;int main()
{ios::sync_with_stdio(false);while(cin>>n){int flag=1,col=-1;r=0,l=0,x=0;for(int i=1;i<=n;i++){cin>>a[i];if(i>1){if(a[i-1]==a[i])//序列相邻值不能相同{flag=0;break;}if(abs(a[i]-a[i-1])>1)//差大于1,获得列数{if(col==-1)col=abs(a[i]-a[i-1]);else{if(col!=abs(a[i]-a[i-1]))//出现了不同的列数,结果是NO{flag=0;}}}else{if(a[i]>a[i-1])//判断矩阵,横向左右两侧分别距离x1的距离x++;if(a[i]<a[i-1])x--;r=max(r,x);if(x<0)l=max(l,abs(x));}}}//cout<<flag<<endl;if(flag){if(col==-1){col=row;}else{//cout<<col<<endl;int h=a[1]%col;if(h==0)h=col;if(h-1<l||r+h>col)flag=0;//cout<<l<<" "<<r<<endl;if(!flag){cout<<"NO"<<endl;}}if(flag){cout<<"YES"<<endl;cout<<row<<" "<<col<<endl;}}elsecout<<"NO"<<endl;}return 0;
}

思路:

比较恶心的模拟题

由于矩阵的排列方式可以知道,任意行相邻的两个位置的数字例如(i,j)和(i+1,j)之间的差一定是一个固定值col,也就是这个矩阵的列数。(如果矩阵只有一行例外)
由于矩阵当中移动的规则只能值在相邻的四个方向上面移动,同一行,向左或者向右移动,那么相邻的元素相差1;同一列,相邻元素差的是是列数col。以样例那个图片为例,同一行1,2,3 相邻的差1,这很明显。同一列,相邻的差3,也很明显。

那么,给定的序列x1,x2,x3…xn,如果不是全都在同一行,也就是相邻元素的差全是1,那么,如果有 xi x i xi+1 x i + 1 之间相差大于1,那么一定就是这个矩阵的列数。还可以知道,如果在这个序列当中出现了两个不一样的列数,那结果肯定是NO。

另外,因为给定的矩阵格式是固定的。如果给出的数据x1,x2,x3…xn满足列数和行数之间的安排,但是会出现以下两种情况,第一种, xi x i xi+1 x i + 1 之间跨度太大,例如序列[1,2,3,4,1],很明显走到4以后是不能走到1的。

第二种,给定的序列超出列数,例如序列[10,13,14,17,16,15],可以看出列数是3,但是从1一直到17画出完整的矩阵就可以知道,15这个元素是不能出现在16的左侧的。因为,列数是3,所以元素10上面的元素分别是7,4,1,也就是10应该在第一列,然而15却出现在了10的左侧。

注意到上面的两个问题,用模拟判断的方式就能解决。

至于输出的行数,直接输出数据范围的最大值即可,行数不影响结果的。

这篇关于cf Educational Codeforces Round 40 C. Matrix Walk的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Codeforces Round #240 (Div. 2) E分治算法探究1

Codeforces Round #240 (Div. 2) E  http://codeforces.com/contest/415/problem/E 2^n个数,每次操作将其分成2^q份,对于每一份内部的数进行翻转(逆序),每次操作完后输出操作后新序列的逆序对数。 图一:  划分子问题。 图二: 分而治之,=>  合并 。 图三: 回溯:

cf 164 C 费用流

给你n个任务,k个机器,n个任务的起始时间,持续时间,完成任务的获利 每个机器可以完成任何一项任务,但是同一时刻只能完成一项任务,一旦某台机器在完成某项任务时,直到任务结束,这台机器都不能去做其他任务 最后问你当获利最大时,应该安排那些机器工作,即输出方案 具体建图方法: 新建源汇S T‘ 对任务按照起始时间s按升序排序 拆点: u 向 u'连一条边 容量为 1 费用为 -c,

Codeforces Round #261 (Div. 2)小记

A  XX注意最后输出满足条件,我也不知道为什么写的这么长。 #define X first#define Y secondvector<pair<int , int> > a ;int can(pair<int , int> c){return -1000 <= c.X && c.X <= 1000&& -1000 <= c.Y && c.Y <= 1000 ;}int m

Codeforces Beta Round #47 C凸包 (最终写法)

题意慢慢看。 typedef long long LL ;int cmp(double x){if(fabs(x) < 1e-8) return 0 ;return x > 0 ? 1 : -1 ;}struct point{double x , y ;point(){}point(double _x , double _y):x(_x) , y(_y){}point op

Codeforces Round #113 (Div. 2) B 判断多边形是否在凸包内

题目点击打开链接 凸多边形A, 多边形B, 判断B是否严格在A内。  注意AB有重点 。  将A,B上的点合在一起求凸包,如果凸包上的点是B的某个点,则B肯定不在A内。 或者说B上的某点在凸包的边上则也说明B不严格在A里面。 这个处理有个巧妙的方法,只需在求凸包的时候, <=  改成< 也就是说凸包一条边上的所有点都重复点都记录在凸包里面了。 另外不能去重点。 int

CF 508C

点击打开链接 import java.util.Arrays;import java.util.Scanner;public class Main {public static void main(String [] args){new Solve().run() ;} }class Solve{int bit[] = new int[608] ;int l

Codeforces 482B 线段树

求是否存在这样的n个数; m次操作,每次操作就是三个数 l ,r,val          a[l] & a[l+1] &......&a[r] = val 就是区间l---r上的与的值为val 。 也就是意味着区间[L , R] 每个数要执行 | val 操作  最后判断  a[l] & a[l+1] &......&a[r] 是否= val import ja

[论文笔记]LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale

引言 今天带来第一篇量化论文LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale笔记。 为了简单,下文中以翻译的口吻记录,比如替换"作者"为"我们"。 大语言模型已被广泛采用,但推理时需要大量的GPU内存。我们开发了一种Int8矩阵乘法的过程,用于Transformer中的前馈和注意力投影层,这可以将推理所需

Codeforces Round 971 (Div. 4) (A~G1)

A、B题太简单,不做解释 C 对于 x y 两个方向,每一个方向至少需要 x / k 向上取整的步数,取最大值。 由于 x 方向先移动,假如 x 方向需要的步数多于 y 方向的步数,那么最后 y 方向的那一步就不需要了,答案减 1 代码 #include <iostream>#include <algorithm>#include <vector>#include <string>

【CF】C. Glass Carving(二分 + 树状数组 + 优先队列 + 数组计数)

这题简直蛋疼死。。。。。 A了一下午 #include<cstdio>#include<queue>#include<cstring>#include<algorithm>using namespace std;typedef long long LL;const int maxn = 200005;int h,w,n;int C1[maxn],C2[maxn];int