将搜索二叉树逆时针旋转45度会发现这是n条值递增的链且头元素相连
如示例
/*
8
4 2 3 1 6 10 9 8
第一条链 4 - 6———————————————————————————10
| |
| |
| ` 第二条链 9
| |
| |
| 第三条链 8
第四条链 2-3
|
第五条链 1
*/
规律如下
1,每条链都是递增的
2,首元素从上到下是递减(可以相等)的
3,每条链的尾元素要比上一条链的首元素小
4.由第n条链到第1条链遍历得到元素由小到大的值。
做法
1每加入一个值找到比这个数小的最大的数a和大于等于它的最小的数b,
(1)如果a没有的话证明这个数是目前的最小的就新开一条链,连上b;
(2)如果a有的话,如果a所在的节点已经有链后缀,则连上b;如果没有
连上a;
2,用set维护最小值否则会超时
#include<cstdio>
#include<set>
#include<utility>
using namespace std;
int a[200000],n,sym[200000];
set<pair<int,int> >s;
set<pair<int,int> >::iterator it;//储存值和下标
int main()
{
scanf("%d",&n);
scanf("%d",&a[0]);
s.insert(make_pair(a[0],0));
for(int i=1;i<n;i++)
{
scanf("%d",&a[i]);
it = s.lower_bound(make_pair(a[i],0));
int firMin,firMax;//拿出比这个数小的最大的数firMin和大于等于它的最小的数firMax,
if(it==s.end())
{
firMax = -1;
}
else firMax = it->second;
if(it==s.begin())
{
firMin = -1;
}
else firMin = (--it)->second;
if(firMin!=-1)
{
if(!sym[firMin])
{
printf("%d ",a[firMin]);
sym[firMin] = 1;
}
else{
printf("%d ",a[firMax]);
}
}
else printf("%d ",a[firMax]);
s.insert(make_pair(a[i],i));
}
return 0;
}