CodeForces 173E

线段树
按能力值从小到大排序,
预处理以第i个人为组长的最大组
然后按能力值反向做更新线段树

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define pb push_back
#define ll o<<1
#define rr o<<1|1
#define mid (l+r)/2
const int N=1e5+100;
struct Node {
    int r,a,id;
    bool operator<(const Node & th)const{
        return r<th.r;
    }
}node[N];
int aa[N],top;
int cc[N];
int qu(int x){
    int ans=0;
    while(x){
        ans+=cc[x];x-=x&-x;
    }
    return ans;
}
void up(int x){
    while(x<=top){
        cc[x]+=1;x+=x&-x;
    }
}

int L,R;
int mx[N<<2];
void update(int l,int r,int o,int x,int v){
    if(l==r){
        mx[o]=max(mx[o],v);return ;
    }
    if(x<=mid)update(l,mid,ll,x,v);
    else update(mid+1,r,rr,x,v);
    mx[o]=max(mx[ll],mx[rr]);
}
int query(int l,int r,int o){
    if(L<=l&&r<=R){
        return mx[o];
    }
    int ans=-1;
    if(L<=mid)ans=max(ans,query(l,mid,ll));
    if(R>mid)ans=max(ans,query(mid+1,r,rr));
    return ans;
}
int num[N];
int ag[N],ra[N];
int ask[N][2];
int ans[N];
int n,k;
int fun(int x){
    //printf("%d %dask\n",ask[x][0],ask[x][1]);
    int l=ag[ask[x][0]],r=ag[ask[x][1]];
    if(l>r)swap(l,r);
    int ans=-1;
    L=lower_bound(aa,aa+top,r-k)-aa+1;R=lower_bound(aa,aa+top,l+k)-aa+1;
    if(R>top||aa[R-1]>l+k)R--;
    if(L<=R)ans=query(1,top,1);
    return ans;
}
vector<int> vv[N];

int main(){
    #ifdef DouBi
    freopen("in.cpp","r",stdin);
    #endif // DouBi

    while(scanf("%d%d",&n,&k)!=EOF){
        for(int i=0;i<n;i++)scanf("%d",&node[i].r),node[i].id=i,ra[i]=node[i].r;
        for(int i=0;i<n;i++)scanf("%d",&node[i].a),aa[i]=node[i].a,ag[i]=aa[i];
        sort(aa,aa+n);top=unique(aa,aa+n)-aa;
        for(int i=0;i<n;i++){
            node[i].a=lower_bound(aa,aa+top,node[i].a)-aa+1;
        }
        sort(node,node+n);
//        for(int i=0;i<n;i++){
//            printf("%d %d\n",node[i].a,node[i].r);
//        }printf("node\n");
        memset(cc,0,sizeof(cc));
        for(int i=0;i<n;i++){
            int j=i;up(node[j].a);
            while(j+1<n&&node[j+1].r==node[i].r){
                j++;up(node[j].a);
            }
            for(int k1=i;k1<=j;k1++){
                int r=lower_bound(aa,aa+top,aa[node[i].a-1]+k)-aa+1;
                if(r>top||aa[r-1]>aa[node[i].a-1]+k)r--;
                int l=lower_bound(aa,aa+top,aa[node[i].a-1]-k)-aa+1;
                num[k1]=qu(r)-qu(l-1);
            }
            i=j;
        }

//        for(int i=0;i<n;i++)printf("%d ",num[i]);printf("num\n");
        for(int i=0;i<n;i++)vv[i].clear();
        int q;scanf("%d",&q);
        for(int i=0;i<q;i++){
            int x,y;scanf("%d%d",&x,&y);x--;y--;
            ask[i][0]=x;ask[i][1]=y;
            if(ra[x]>=ra[y])vv[x].pb(i);
            if(ra[y]>=ra[x])vv[y].pb(i);
        }

        memset(mx,-1,sizeof(mx));
        memset(ans,-1,sizeof(ans));
        for(int i=n-1;i>=0;i--){
            int j=i;update(1,top,1,node[j].a,num[j]);
            while(j-1>=0&&node[j-1].r==node[i].r){
                j--;update(1,top,1,node[j].a,num[j]);
            }
            for(int k2=j;k2<=i;k2++){
                int id=node[k2].id;
                for(int k1=0;k1<vv[id].size();k1++){
                    ans[vv[id][k1]]=max(ans[vv[id][k1]],fun(vv[id][k1]));
                }
            }
            i=j;
        }
        for(int i=0;i<q;i++){
            printf("%d\n",ans[i]);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值