51nod1287【线段树+折半搜索】

来源:互联网 发布:综琼瑶 知君用心 编辑:程序博客网 时间:2024/05/17 05:58

思路:

其实就是每次折半找一下对吧,但是要维护出一个区间最(大)值,所以套一个线段树就可以轻松解决了。

#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 111 2 0 4 3 2 1 5 72 8 0 7 6 5 3 4 5 6 5*/


0 0