题目
n个数,每次找到第一个单增子序列,
输出这些数并删除,然后找第二个……
至所有数都被找出
暴力做肯定会T的吖
思路来源
https://blog.csdn.net/qq_28954601/article/details/78122766
心得
博主的题解和代码写的都不错 为博主点赞
注意到第二个序列的尾部一定比第一个序列的尾部的值小,
不然第二个序列的尾部的值就被续到第一个序列的尾部了
同理,有第三个序列的尾部比第二个序列的尾部的值小……
以此类推,则尾部的值是单减的
每次二分找到比当前插入值小的最小位置并缀在该序列后面,
找不到就新创建一个序列
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=2e5+10;
deque<int>q[maxn];
int n,a[maxn],cnt;
int find(int x)
{
int l=0,r=cnt;
while(l<r)
{
int mid=(l+r)>>1;
if(q[mid].back()<x)r=mid;//<=r的均可
else l=mid+1;//<l的均不可
}
//l==r时 判l可不可
if(l==cnt)return -1;
return l;
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;++i)
{
scanf("%d",&a[i]);
int res=find(a[i]);
if(res==-1)q[cnt++].push_back(a[i]);
else q[res].push_back(a[i]);
}
for(int i=0;i<cnt;++i)
{
printf("%d",q[i].front());
q[i].pop_front();
while(!q[i].empty())
{
printf(" %d",q[i].front());
q[i].pop_front();
}
puts("");
}
return 0;
}