[Codeforces Round #522 (Div. 2, based on Technocup 2019 Elimination Round 3)][C. Playing Piano]
http://codeforces.com/contest/1079/problem/C
题目大意:给出一个数列a[n],让构造一个满足下列条件的数列b[n]:如果a[i]>a[i-1]那么b[i]>b[i-1],如果a[i]<a[i-1]那么b[i]<b[i-1],如果a[i]==a[i-1],那么b[i]!=b[i-1].其中1<=b[i]<=5 1<=a[i]<=2*1e5.
题解:dp[i][j]表示在位置i处取j时是否成立,如果成立则dp[i][j]=1,而这个成立的条件就是这个状态之前的状态成立dp[i-1][k]=1,这样就可以O(5*N)解决这个问题(对于这种要求构造出数列并且新数列的取值很少的题目,直接枚举取值利用dp方式做即可)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 using namespace std; 7 typedef long long ll; 8 int a[100005],b[100005]; 9 int dp[100005][6],pre[100005][6]; 10 int main(){ 11 // freopen("in.txt","r",stdin); 12 int n; 13 int f=1; 14 int tot1=0; 15 int tot2=0; 16 cin>>n; 17 for(int i=1;i<=n;i++){ 18 scanf("%d",&a[i]); 19 } 20 for(int i=1;i<=5;i++){ 21 dp[1][i]=1; 22 } 23 for(int i=1;i<n;i++){ 24 for(int j=1;j<=5;j++){ 25 if(!dp[i][j])continue; 26 if(a[i+1]>a[i]){ 27 for(int k=j+1;k<=5;k++){ 28 dp[i+1][k]=1; 29 pre[i+1][k]=j; 30 } 31 } 32 else if(a[i+1]<a[i]){ 33 for(int k=1;k<j;k++){ 34 dp[i+1][k]=1; 35 pre[i+1][k]=j; 36 } 37 } 38 else{ 39 for(int k=1;k<=5;k++){ 40 if(k==j)continue; 41 dp[i+1][k]=1; 42 pre[i+1][k]=j; 43 } 44 } 45 } 46 } 47 for(int i=1;i<=5;i++){ 48 if(dp[n][i]){ 49 for(int j=n;j>=1;j--){ 50 b[j]=i; 51 i=pre[j][i]; 52 } 53 f=0; 54 break; 55 } 56 } 57 if(f){printf("-1\n");return 0;} 58 for(int i=1;i<=n;i++){ 59 printf("%d",b[i]); 60 char cc=(i==n)?'\n':' '; 61 printf("%c",cc); 62 } 63 return 0; 64 }