题目
解法
这不是用平衡树随便搞吗
怎么可能用这么复杂的代码!!!(╯‵□′)╯︵┻━┻
实在不行用离散化加主席树也可以啊
怎么可能打线段树啊(╯‵□′)╯︵┻━┻
树状数组加二分也行啊,你不嫌弃直接树状数组也可以啊
也不想打啊(╯‵□′)╯︵┻━┻
平衡树不是有STL吗?
不用STL(╯‵□′)╯︵┻━┻
那就用整体二分啊
不会(╯‵□′)╯︵┻━┻
然后后面学了。
这里,我们仔细思考一下,这个其实就是询问第(k)大,但是这个(k)竟然是递增的,这意味着我们可以使用堆,然后每次查询完一次第(k)大,然后把堆顶踢出去,这样(k+1)大就又是堆顶啦!!!!完美。
然后我WA了。。。。
仔细思考一下,堆顶的元素虽然在连续的询问中不可能再出现了,但是如果询问完第(k)大后插入个比它小的作替死鬼,这样下次问第(k+1)大就还是这个堆顶了啊。
于是我们需要一个可以有后悔操作的工具堆,没错,就是对顶堆。
我们把删除的数字全部放到一个大根堆中,如果这个时候插入的数字(x)比堆头小,那么就把(x)插入到大根堆中,把大根堆原来的堆顶插入回小根堆中参与询问。
对顶堆NB!!!!
当然我是手打堆,代码好长(╯‵□′)╯︵┻━┻。
代码
(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
",x);
}
if(t==m)break;
}
return 0;
}