本文主要是介绍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的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!