小Paul想学弹钢琴。他已经有了一首想要开始演奏的旋律。为简单起见,他将这个旋律表示为键号序列a1,a2,…,an:数字越大,它就越靠近钢琴键盘的右侧。
Paul非常聪明,知道关键是正确地为他要演奏的音符分配手指。如果他选择不方便的指法,那么他将浪费很多时间尝试学习如何用这些手指演奏旋律,他可能不会成功。
我们用数字1到5来表示手指。我们称任何手指数字序列b1,…,bn为指法。如果对于所有1≤i≤n−1,以下条件成立,则指法很方便:
如果ai<ai+1,则bi<bi+1,因为否则Paul需要从键盘上拿下手来演奏(i+1)次音符; 如果ai>ai+1,则bi>bi+1,原因相同; 如果ai=ai+1,则bi≠bi+1,因为连续使用同一个手指是愚蠢的,请注意bi和bi+1之间有≠而不是=。
请提供任何方便的指法,或者发现没有。
输入 第一行包含一个整数n(1≤n≤105),表示音符数量。
第二行包含n个整数a1,a2,…,an(1≤ai≤2⋅105),表示键盘上的音符位置。
输出 如果没有方便的指法,请打印-1。否则,打印n个数字b1,b2,…,bn,每个数字从1到5,用空格分隔,表示便利的指法。
Examples
input
Copy
5 1 1 4 2 2
output
Copy
1 4 5 4 5
input
Copy
7 1 5 7 8 10 3 1
output
Copy
1 2 3 4 5 4 3
input
Copy
19 3 3 7 9 8 8 8 8 7 7 7 7 5 3 3 3 3 8 8
output
Copy
1 3 4 5 4 5 4 5 4 5 4 5 4 3 5 4 3 5 4
题解:
遇到这种限制比较多的构造,且用于构造的数比较小,那我们可以直接进行dfs来求答案,注意所给的限制条件全都要用上
#include <cstdio>
#include <cstring>
#include <algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
#define int long long
typedef pair<int,int> PII;
int mod = 1e9 + 7;
int a[100050];
int n;
int vis[100050][11];
int num[100050];
int dfs(int x)
{
if(x == n)
return 1;
for(int i = 1;i <= 5;i++)
{
if(!vis[x + 1][i])
{
if((a[x] == a[x + 1]&&num[x] != i)||(a[x] > a[x + 1]&&num[x] > i)||(a[x] < a[x + 1]&&num[x] < i))
{
num[x + 1] = i;
vis[x + 1][i] = 1;
if(dfs(x + 1))
return 1;
// dfs(x + 1);
// vis[x + 1][i] = 0;
}
}
}
return 0;
}
void solve()
{
cin >> n;
for(int i = 1;i <= n;i++)
{
cin >> a[i];
}
int f = 0;
for(int i = 1;i <= 5;i++)
{
num[1] = i;
if(dfs(1))
{
f = 1;
break;
}
}
if(f)
{
for(int i = 1;i <= n;i++)
cout << num[i] <<" ";
}
else
{
cout <<"-1";
}
}
signed main()
{
// ios::sync_with_stdio(0 );
// cin.tie(0);cout.tie(0);
int t = 1;
// cin >> t;
while(t--)
{
solve();
}
}