19徐州网络赛E 线段树加离散化

题目链接:https://nanti.jisuanke.com/t/41387

 

 

按wi的值建立权值线段树维护值为wi出现的最后位置,对于第i个人的答案,查询线段树[wi+m,max]区间的最大位置pos,令如果pos-i-1小于等于-1则是在i之后不存在大于等于wi+m的人,否则第i个人的答案即为pos-i-1。由于wi范围过大所以需对wi离散化

#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
#define ll long long
#define ls l,mid,rt<<1
#define rs mid+1,r,rt<<1|1
#define maxn 1000010
int n,m,mx[maxn<<2];
ll w[maxn],x[maxn],li[maxn],ans[maxn];
void pushup(int rt)
{
    mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);
}
void update(int L,int c,int l,int r,int rt)
{
    if(l==r)
    {
        mx[rt]=c;
        return ;
    }
    int mid=l+r>>1;
    if(L<=mid)update(L,c,ls);
    else update(L,c,rs);
    pushup(rt);
}
int query(int L,int R,int c,int l,int r,int rt)
{
    if(L<=l&&R>=r)
    {
        return mx[rt];
    }
    int mid=l+r>>1,ret=0;
    if(L<=mid)ret=max(ret,query(L,R,c,ls));
    if(R>mid)ret=max(ret,query(L,R,c,rs));
    return ret;
}
int main()
{
    scanf("%d%d",&n,&m);
    int tot=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&w[i]);
        x[++tot]=w[i];
        x[++tot]=w[i]+m;
    }
    sort(x+1,x+1+tot);
    int nx=unique(x+1,x+1+tot)-x-1;
    int L;
    for(int i=1;i<=n;i++)
    {
        L=lower_bound(x+1,x+1+nx,w[i])-x;
        update(L,i,1,nx,1);
    }
    for(int i=1;i<=n;i++)
    {
        L=lower_bound(x+1,x+1+nx,w[i]+m)-x;
        L=query(L,nx,i,1,nx,1);
        if(L==-1)ans[i]=-1;
        else ans[i]=L-i-1;
        if(ans[i]<-1)ans[i]=-1;
    }
    for(int i=1;i<n;i++)
    printf("%lld ",ans[i]);
    printf("%lld\n",ans[n]);
    return 0;
}

 

posted on 2019-09-07 21:44  che027  阅读(133)  评论(0编辑  收藏  举报

导航