记录一个菜逼的成长。。
虽然只是L2级,但是感觉比一些L3还要难写。。
其实就是建树的一个过程,如果可以把序列划分成两个部分,一部分的值都比这个节点小,另一部分的值都大于等于这个节点的值
对于每一个节点,都如此判断,递归进行。
这题要注意很多细节。
通不过的可以测试下
Sample1:
2
2 1
Sample2:
3
3 1 2
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
#define ALL(v) (v).begin(),(v).end()
#define cl(a,b) memset(a,b,sizeof(a))
#define pb push_back
typedef long long LL;
const int maxn = 2000 + 10;
int a[maxn],flag,vis[maxn];
struct node{
int l,r,v;
}tree[maxn];
bool check1(int l,int r,int &pos)
{
for( int i = l+1; i <= r; i++ ){
if(a[i] >= a[l]){
pos = i;
for( int j = i; j <= r; j++ ){
if(a[j] < a[l])return false;
}
return true;
}
}
return true;
}
bool check2(int l,int r,int &pos)
{
for( int i = l+1; i <= r; i++ ){
if(a[i] < a[l]){
pos = i;
for( int j = i; j <= r; j++ ){
if(a[j] >= a[l])return false;
}
return true;
}
}
return true;
}
int ind,ok;
void build(int l,int r)
{
if(flag || l > r)return ;
tree[ind++].v = a[l];
if(l == r)return ;
int pos1 = 0,pos2 = 0;
bool ret1 = check1(l,r,pos1);
bool ret2 = check2(l,r,pos2);
//cout<<ret1<<' '<<ret2<<' '<<pos1<<' '<<pos2<<endl;
if(!ret1 && !ret2){
flag = 1;
return ;
}
if(!ok){
if((ret1&&ret2) || (ret1&&!ret2))ok = 1;
else ok = 2;
}
int num;
if(ret1&&ret2)num = ok;
else if(ret1&&!ret2)num = 1;
else num = 2;
if(num != ok){
flag = 1;
return ;
}
if(num == 1){
tree[ind-1].l = l+1;
tree[ind-1].r = pos1;
build(l+1,pos1?pos1-1:r);
build(pos1?pos1:r+1,r);
}
else {
tree[ind-1].l = l+1;
tree[ind-1].r = pos2;
build(l+1,pos2?pos2-1:r);
build(pos2?pos2:r+1,r);
}
}
void post_print(int t)
{
if(vis[t])return ;
vis[t] = 1;
post_print(tree[t].l);
post_print(tree[t].r);
if(flag)cout<<tree[t].v,flag = 0;
else cout<<" "<<tree[t].v;
}
int main()
{
int n;
while(cin>>n){
for( int i = 1; i <= n; i++ )
cin>>a[i];
flag = 0,ind = 1,ok = 0 ;
build(1,n);
// for( int i = 1; i <= n; i++ ){
// printf("%d %d %d %d\n",i,tree[i].l,tree[i].r,tree[i].v);
// }
// puts("");
if(flag)puts("NO");
else {
puts("YES");
flag = 1;vis[0] = 1;
post_print(1);
puts("");
}
}
return 0;
}