思路:
其实就是每次折半找一下对吧,但是要维护出一个区间最(大)值,所以套一个线段树就可以轻松解决了。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
const int N=5e4+10;
struct asd{
int Left,Right;
int val;
}node[N<<2];
void Build(int num,int Left,int Right){
node[num].Left = Left;
node[num].Right = Right;
if(Left == Right){
scanf("%d",&node[num].val);
return;
}
int Mid=(Left+Right)>>1;
Build(num<<1,Left,Mid);
Build(num<<1|1,Mid+1,Right);
node[num].val=max(node[num<<1].val,node[num<<1|1].val);
}
int DFS(int num,int val){
if(node[num].val<val) return INF;
if(node[num].Left == node[num].Right)
return node[num].Left;
if(node[num<<1].val>=val)
return DFS(num<<1,val);
else
return DFS(num<<1|1,val);
}
void ADD(int num,int s)
{
if(node[num].Left == node[num].Right && node[num].Left == s){
node[num].val++;
return;
}
int Mid=(node[num].Left+node[num].Right)>>1;
if(Mid>=s)
ADD(num<<1,s);
else
ADD(num<<1|1,s);
node[num].val=max(node[num<<1].val,node[num<<1|1].val);
}
int query(int num,int s)
{
if(node[num].Left == node[num].Right && node[num].Left == s)
return node[num].val;
int Mid=(node[num].Left+node[num].Right)>>1;
if(Mid>=s)
return query(num<<1,s);
else
return query(num<<1|1,s);
}
int main()
{
int n,m,x,pos;
scanf("%d%d",&n,&m);
Build(1,1,n);
for(int i=1;i<=m;i++)
{
scanf("%d",&x);
pos=DFS(1,x);
if(pos==1||pos==INF) continue;
ADD(1,pos-1);
}
for(int i=1;i<=n;i++)
printf("%d\n",query(1,i));
return 0;
}
/*
9 11
1 2 0 4 3 2 1 5 7
2 8 0 7 6 5 3 4 5 6 5
*/