codeforces 91b Queue

来源:互联网 发布:mac host 生效 编辑:程序博客网 时间:2024/05/21 10:42

http://codeforces.com/problemset/problem/91/B


题意是给你一个数组,对每个数求它最右的一个比他小的数和他的距离。

 

考虑二分该数右边的区间,先求(mid,r)的最小值,如果小于该数就接着二分

区间最小值用线段树维护。


#include <iostream>#include <climits>using namespace std;const int MAXN=100010;int num[MAXN];template<class T>struct Segtree {#define ls (o<<1)#define rs (o<<1)|1    T data[MAXN<<2];    void pushup(int o) {        data[o]=min(data[ls],data[rs]);    }    void build(int o,int l,int r) {        if(l==r) {            data[o]=num[l];            return;        }        int mid=(l+r)>>1;        build(ls,l,mid);        build(rs,mid+1,r);        pushup(o);    }    T query(int o,int l,int r,int x,int y) {        if(l>=x && r<=y) {            return data[o];        }        int mid=(l+r)>>1;        if(y<=mid) return query(ls,l,mid,x,y);        if(x>mid)  return query(rs,mid+1,r,x,y);        return min(query(ls,l,mid,x,y),query(rs,mid+1,r,x,y));    }};Segtree<int> tree;int n;int ans[MAXN];int solve (int x,int t) {    int l=x,r=n;    while(r-l>=3){        int mid=(l+r)>>1;       // cout<<"mid= "<<mid<<endl;        if(tree.query(1,1,n,mid,r)<t){            l=mid;            continue;        }        if(tree.query(1,1,n,l,mid)<t){            r=mid;            continue;        }        break;    }   // cout<<l<<' '<<r<<endl;    if(r-l>=3)        return -1;    int ans=0;    for(int i=r;i>=l;i--){        if(num[i]<t){            ans=i;            break;        }    }    if(ans==0)        return -1;    ans=ans-x-1;    return ans;}int main(){    ios::sync_with_stdio(false);    cin.tie(nullptr);    cout.tie(nullptr);    cin>>n;    for(int i=1;i<=n;i++){        cin>>num[i];    }    tree.build(1,1,n);    for(int i=1;i<=n;i++){     //   cout<<"i= "<<i<<endl;        ans[i]= solve(i,num[i]);    }    for(int i=1;i<=n;i++)        cout<<ans[i]<<' ';    return 0;}


原创粉丝点击