二分+线段树的经典题目
#include<bits/stdc++.h>
using namespace std;
int num[100000];
struct node
{
int l,r;
long long nsum;
}segtree[300000];
void build(int i,int l,int r)
{
segtree[i].l=l;
segtree[i].r=r;
if(l==r)
{
segtree[i].nsum=num[l];
return;
}
int mid=(l+r)>>1;
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
segtree[i].nsum=max(segtree[i<<1].nsum,segtree[i<<1|1].nsum);
}
void add(int i,int a,int b,long long c)
{
if(segtree[i].l==segtree[i].r)
{
segtree[i].nsum+=c;
return;
}
int mid=(segtree[i].l+segtree[i].r)>>1;
if(b<=mid)
add(i<<1,a,b,c);
else if(a>mid)
add(i<<1|1,a,b,c);
else
{
add(i<<1,a,mid,c);
add(i<<1|1,mid+1,b,c);
}
segtree[i].nsum=max(segtree[i<<1].nsum,segtree[i<<1|1].nsum);
}
long long query(int i,int a,int b)
{
if(segtree[i].l==a&&segtree[i].r==b)
{
return segtree[i].nsum;
}
int mid=(segtree[i].l+segtree[i].r)>>1;
if(b<=mid)
return query(i<<1,a,b);
else if(a>mid)
return query(i<<1|1,a,b);
else
return max(query(i<<1,a,mid),query(i<<1|1,mid+1,b));
}
int main()
{
int n,m,i,lef,rig,mid,h;
while(cin>>n>>m)
{
for(i=1;i<=n;i++)
scanf("%d",&num[i]);
build(1,1,n);
while(m--)
{
scanf("%d",&h);
if(query(1,1,n)<h)
continue;
lef=1;rig=n;
while(lef<=rig)
{
mid=(lef+rig)>>1;
if(query(1,lef,mid)>=h)
rig=mid-1;
else
lef=mid+1;
}
if(lef>1)
add(1,lef-1,lef-1,1);
}
for(i=1;i<=n;i++)
printf("%d\n",query(1,i,i));
}
}