分组

题目描述
Bsny所在的精灵社区有n个居民,每个居民有一定的地位和年龄,ri表示第i个人的地位,ai表示第i个人的年龄。

最近社区里要举行活动,要求几个人分成一个小组,小组中必须要有一个队长,要成为队长有这样的条件:

1、队长在小组中的地位应该是最高的(可以并列第一);

2、小组中其他成员的年龄和队长的年龄差距不能超过K。

有些人想和自己亲密的人组在同一个小组,同时希望所在的小组人越多越好。比如x和y想在同一个小组,同时希望它们所在的小组人越多越好,当然,它们也必须选一个符合上述要求的队长,那么问你,要同时包含x和y的小组,最多可以组多少人?

输入
第一行两个整数n和K;

接下来一行输入n个整数:r1, r2, …, rn

接下来一行输入n个整数:a1, a2, …, an

接下来输入Q表示有Q个询问;

接下来Q行每行输入x, y,表示询问:当x和y组在同一个小组,它们小组最多可以有多少人(x和y也有可能被选为队长,只要它们符合条件)。

输出
对于每个询问,输出相应的答案,每个答案占一行。

当x和y无法在同一组时,输出-1(比如x的年龄是1, y的年龄是100,K=1,无论谁当队长,x和y两者中,总会有人跟队长的年龄差距超过K,那么输出-1)。

样例输入
5 1
1 5 4 1 2
4 4 3 2 2
4
5 3
2 3
2 5
4 1
样例输出
4
3
-1
4
提示
【样例解释】

询问1:当第5个人和第3个人想在一组时,小组成员可以有{1, 3, 4, 5},选择3当队长,而2不可以加入,因为2加入的话,5和2的年龄差距为2,超过K=1了;

询问2:当第2个人和第3个人想在一组时,可以选择{1, 2, 3};

询问3:当2和5想在一起时,无法满足要求;

询问4:当4和1想在一起时,可以选择{1, 3, 4, 5};

【数据规模】

20%的数据:2≤n≤100,0≤ k≤100,1≤ ri, ai ≤100,1≤ q≤ 100;

40%的数据:2≤ n≤1000,0≤ k≤ 1000,1≤ ri, ai ≤ 1000,1≤ q≤ 1000;

60%的数据:2≤ n≤ 104,0≤ k≤ 109,1≤ ri, ai ≤ 109, 1≤ q≤ 104;

100%的数据:2≤ n≤ 105,0≤ k≤ 109,1≤ ri, ai ≤ 109,1≤ q≤ 105,1≤ x, y≤ n, x≠y。

题解
预处理每个人当领导的最大组队人数。
根据地位排序,利用数据结构记录年龄,离线处理即可。

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
    int x=0;char ch=getchar();
    while (ch<'0'||ch>'9') ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x;       
}
struct node{int id,f,r,a,x,y;}a[200005];
struct node1{int id,r,x,y;}q[100005];
int ls[1000005],p[1000005];
int mx[4000005],ans[100005];
int n,k,Q,tot;
bool cmp(node a,node b){return a.r<b.r;}
bool cmpq(node1 a,node1 b){return a.r>b.r;}
inline int lowbit(int x){return x&-x;}
void update_p(int x,int y){for (int i=x;i<=tot;i+=lowbit(i))p[i]+=y;}
int getsum(int x)
{
     int ans=0;
     for (int i=x;i;i-=lowbit(i))
         ans+=p[i];
     return ans; 
}
void change(int k,int l,int r,int x,int y)
{
     if (l==r)
     {
         mx[k]=max(mx[k],y);
         return;
     }
     int mid=(l+r)>>1;
     if (x<=mid) change(k<<1,l,mid,x,y);
     else change(k<<1|1,mid+1,r,x,y);
     mx[k]=max(mx[k<<1],mx[k<<1|1]);
}
int query(int k,int l,int r,int x,int y)
{
    if (l==x&&r==y) return mx[k];
    int mid=(l+r)>>1;
    if (y<=mid) return query(k<<1,l,mid,x,y);
    else if (x>mid) return query(k<<1|1,mid+1,r,x,y);
    else return max(query(k<<1,l,mid,x,mid),query(k<<1|1,mid+1,r,mid+1,y));
}
int find(int x)
{
    int l=1,r=tot;
    while (l!=r)
    {
        int mid=(l+r)>>1;
        if (ls[mid]>=x) r=mid;else l=mid+1;
    }
    return l;
}
int main()
{
    n=read();k=read();
    for (int i=1;i<=n;i++)
    {
        a[i].r=read();ls[++tot]=a[i].r;a[i].id=i;
    }
    for (int i=1;i<=n;i++)
    {
        a[i].a=read();ls[++tot]=a[i].a;
        a[i].x=a[i].a-k-1;a[i].y=a[i].a+k;
        ls[++tot]=a[i].x;ls[++tot]=a[i].y;
    }
    Q=read();
    for (int i=1;i<=Q;i++)
    {
        int x=read(),y=read();
        q[i].r=max(a[x].r,a[y].r);
        q[i].y=min(a[x].a+k,a[y].a+k);
        q[i].x=max(a[x].a-k,a[y].a-k);
        q[i].id=i;
        ls[++tot]=q[i].x;ls[++tot]=q[i].y;
    }
    sort(ls+1,ls+tot+1);
    sort(a+1,a+n+1,cmp);
    int pos;
    for (int i=1;i<=n;i=pos)
    {
        a[i].r=find(a[i].r);a[i].a=find(a[i].a);update_p(a[i].a,1);
        pos=i+1;
        while (a[i].r==find(a[pos].r)&&pos<=n)
        {      
              a[pos].r=find(a[pos].r);
              a[pos].a=find(a[pos].a);
              update_p(a[pos].a,1);
              pos++;
        }
        for (int j=i;j<pos;j++){a[j].f=getsum(find(a[j].y))-getsum(find(a[j].x));}
    }
    sort(q+1,q+Q+1,cmpq);
    int now=n;
    for (int i=1;i<=Q;i++)
    {
        q[i].x=find(q[i].x);q[i].y=find(q[i].y);q[i].r=find(q[i].r);
        //cout<<q[i].id<<" "<<q[i].r<<" "<<q[i].x<<" "<<q[i].y<<endl;
        while (a[now].r>=q[i].r)
        {
              //cout<<a[now].a<<" "<<a[now].f<<endl;
              change(1,1,tot,a[now].a,a[now].f);
              now--;
        }
        if (q[i].x<=q[i].y)ans[q[i].id]=query(1,1,tot,q[i].x,q[i].y);
        else ans[q[i].id]=-1;
        if (ans[q[i].id]==0) ans[q[i].id]=-1;
    }
    for (int i=1;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、付费专栏及课程。

余额充值