正题
题目链接:https://jzoj.net/senior/#contest/show/2990/2
题目大意
一个小队满足要求
- 队长的地位最高
- 所有队员和队长的年龄差不超过kkk
给出nnn个人的地位和年龄,qqq个询问
每次询问一组(x,y)(x,y)(x,y)求若(x,y)(x,y)(x,y)在同一个队里那这个队的最多人数。
解题思路
我们将年龄离散化然后按照地位从大到小排序。
然后我们用树状数组维护出每个人作为队长时小队的最多人数。
之后我们对于每个询问(x,y)(x,y)(x,y),默认yyy的地位大于xxx。
我们按照地位从大到小枚举,对于每个(x,y)(x,y)(x,y),我们搞定满足条件的年龄范围(l,r)(l,r)(l,r),然后将地位比yyy大的最多人数都丢进线段树里,然后查询区间(l,r)(l,r)(l,r)即可。
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int N=1e5+10;
struct node{int r,w,num;
}a[N];
int n,k,Q,cnt,ans[N];
int b[N],num[N],l[N],r[N],v[N];
vector<int> q[N];
struct Tree_Array{#define lowbit(x) (x&-x)int t[N];void Change(int x,int z){while(x<=n){t[x]+=z;x+=lowbit(x);}return;}int Ask(int x){int ans=0;while(x){ans+=t[x];x-=lowbit(x);}return ans;}#undef lowbit(x)
}TA;
struct Seq_Tree{struct Tree_node{int l,r,w;}t[N*4];void Build(int x,int l,int r){t[x].l=l;t[x].r=r;t[x].w=-1;if(l==r)return;int mid=(l+r)/2;Build(x*2,l,mid);Build(x*2+1,mid+1,r);}void Change(int x,int pos,int z){if(t[x].l==t[x].r){t[x].w=max(t[x].w,z);return;}int mid=(t[x].l+t[x].r)>>1;if(pos<=mid) Change(x*2,pos,z);else Change(x*2+1,pos,z);t[x].w=max(t[x*2].w,t[x*2+1].w);}int Ask(int x,int l,int r){if(t[x].l==l&&t[x].r==r)return t[x].w;int mid=(t[x].l+t[x].r)>>1;if(r<=mid) return Ask(x*2,l,r);if(l>mid) return Ask(x*2+1,l,r);return max(Ask(x*2,l,mid),Ask(x*2+1,mid+1,r));}
}T;
bool cmp(node x,node y)
{return x.r>y.r;}
int main()
{scanf("%d%d",&n,&k);for(int i=1;i<=n;i++)scanf("%d",&a[i].r),a[i].num=i;for(int i=1;i<=n;i++)scanf("%d",&a[i].w),b[++cnt]=a[i].w;sort(b+1,b+1+cnt);cnt=unique(b+1,b+1+cnt)-b-1;sort(a+1,a+1+n,cmp);for(int i=1;i<=n;i++){num[a[i].num]=i;l[i]=lower_bound(b+1,b+1+cnt,a[i].w-k)-b;r[i]=upper_bound(b+1,b+1+cnt,a[i].w+k)-b-1;a[i].w=lower_bound(b+1,b+1+cnt,a[i].w)-b;TA.Change(a[i].w,1);}scanf("%d",&Q);for(int i=1;i<=Q;i++){int x,y;scanf("%d%d",&x,&y);x=num[x];y=num[y];if(x<y)swap(x,y);q[y].push_back(i);v[i]=x;}int w=1;T.Build(1,1,cnt);for(int i=1;i<=n;i++){while(w<=n&&a[w].r>=a[i].r){int val=TA.Ask(r[w])-TA.Ask(l[w]-1);T.Change(1,a[w].w,val);w++;}for(int j=0;j<q[i].size();j++){int x=v[q[i][j]],y=i;int L=max(l[x],l[y]),R=min(r[x],r[y]);if(L>R) ans[q[i][j]]=-1;else ans[q[i][j]]=T.Ask(1,L,R);}TA.Change(a[i].w,-1);}for(int i=1;i<=Q;i++)printf("%d\n",ans[i]);
}