黑盒子

题目

题目

解法

这不是用平衡树随便搞吗

怎么可能用这么复杂的代码!!!(╯‵□′)╯︵┻━┻

实在不行用离散化加主席树也可以啊

怎么可能打线段树啊(╯‵□′)╯︵┻━┻

树状数组加二分也行啊,你不嫌弃直接树状数组也可以啊

也不想打啊(╯‵□′)╯︵┻━┻

平衡树不是有STL吗?

不用STL(╯‵□′)╯︵┻━┻

那就用整体二分啊

不会(╯‵□′)╯︵┻━┻

然后后面学了。

这里,我们仔细思考一下,这个其实就是询问第 k k k大,但是这个 k k k竟然是递增的,这意味着我们可以使用堆,然后每次查询完一次第 k k k大,然后把堆顶踢出去,这样 k + 1 k+1 k+1大就又是堆顶啦!!!!完美。

然后我WA了。。。。

仔细思考一下,堆顶的元素虽然在连续的询问中不可能再出现了,但是如果询问完第 k k k大后插入个比它小的作替死鬼,这样下次问第 k + 1 k+1 k+1大就还是这个堆顶了啊。

于是我们需要一个可以有后悔操作的工具堆,没错,就是对顶堆。

我们把删除的数字全部放到一个大根堆中,如果这个时候插入的数字 x x x比堆头小,那么就把 x x x插入到大根堆中,把大根堆原来的堆顶插入回小根堆中参与询问。

对顶堆NB!!!!

当然我是手打堆,代码好长(╯‵□′)╯︵┻━┻。

代码

O ( n l o g n ) O(nlogn) O(nlogn)

#include<cstdio>
#include<cstring>
#define  N  31000
using  namespace  std;
int  a[N],n,m,b[N];
inline  void  wap(int  &x,int  &y){
    
    int  t=x;x=y;y=t;}
struct  xiao_dui
{
    
    
	int  a[N],tot;
	void  ins(int  x)
	{
    
    
		a[++tot]=x;int  now=tot;
		while(now>1)
		{
    
    
			int  i=now>>1;
			if(a[i]>a[now])wap(a[i],a[now]),now=i;
			else  break;
		}
	}
	int  pop()
	{
    
    
		int  ans=a[1];wap(a[1],a[tot]);tot--;
		int  now=1;
		while((now<<1)<=tot)
		{
    
    
			int  i=now<<1;
			if(i<tot  &&  a[i+1]<a[i])i++;
			if(a[i]<a[now])wap(a[i],a[now]),now=i;
			else  break;
		}
		return  ans;
	}
}a1;
struct  da_dui
{
    
    
	int  a[N],tot;
	void  ins(int  x)
	{
    
    
		a[++tot]=x;int  now=tot;
		while(now>1)
		{
    
    
			int  i=now>>1;
			if(a[i]<a[now])wap(a[i],a[now]),now=i;
			else  break;
		}
	}
	int  pop()
	{
    
    
		int  ans=a[1];wap(a[1],a[tot]);tot--;
		int  now=1;
		while((now<<1)<=tot)
		{
    
    
			int  i=now<<1;
			if(i<tot  &&  a[i+1]>a[i])i++;
			if(a[i]>a[now])wap(a[i],a[now]),now=i;
			else  break;
		}
		return  ans;
	}
	int  top(){
    
    return  tot==0?-999999999:a[1];}
}a2;
int  main()
{
    
    
	scanf("%d%d",&n,&m);
	for(int  i=1;i<=n;i++)scanf("%d",&a[i]);
	for(int  i=1;i<=m;i++)
	{
    
    
		scanf("%d",&b[i]);
		b[i]=b[i]-i+1;
	}
	int  t=0;
	for(int  i=1;i<=n;i++)
	{
    
    
		if(a[i]<a2.top())
		{
    
    
			a1.ins(a2.pop());
			a2.ins(a[i]);
		}
		else  a1.ins(a[i]);
		while(a1.tot==b[t+1]  &&  t<m)
		{
    
    
			t++;
			int  x=a1.pop();a2.ins(x);
			printf("%d\n",x);
		}
		if(t==m)break;
	}
	return  0;
}

猜你喜欢

转载自blog.csdn.net/zhangjianjunab/article/details/107612866
今日推荐