CodeForces - 847B Preparing for Merge Sort(二分+思维)

题目

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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Code92007

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值