题目
Bsny所在的精灵社区有\(n\)个居民,每个居民有一定的地位和年龄,\(r_i\)表示第\(i\)个人的地位,\(a_i\)表示第\(i\)个人的年龄。
最近社区里要举行活动,要求几个人分成一个小组,小组中必须要有一个队长,要成为队长有这样的条件:
1、队长在小组中的地位应该是最高的(可以并列第一);
2、小组中其他成员的年龄和队长的年龄差距不能超过\(K\)。
有些人想和自己亲密的人组在同一个小组,同时希望所在的小组人越多越好。比如\(x\)和\(y\)想在同一个小组,同时希望它们所在的小组人越多越好,当然,它们也必须选一个符合上述要求的队长,那么问你,要同时包含\(x\)和\(y\)的小组,最多可以组多少人?
第一行两个整数\(n\)和\(K\);
接下来一行输入\(n\)个整数:\(r_1, r_2,\dots, r_n\)
接下来一行输入\(n\)个整数:\(a_1, a_2,\dots, a_n\)
接下来输入\(Q\)表示有\(Q\)个询问;
接下来\(Q\)行每行输入\(x, y\),表示询问:当\(x\)和\(y\)组在同一个小组,它们小组最多可以有多少人(\(x\)和\(y\)也有可能被选为队长,只要它们符合条件)。
对于每个询问,输出相应的答案,每个答案占一行。
当\(x\)和\(y\)无法在同一组时,输出-1(比如\(x\)的年龄是1, \(y\)的年龄是100,\(K=1\),无论谁当队长,\(x\)和\(y\)两者中,总会有人跟队长的年龄差距超过\(K\),那么输出-1)。
Sample Input
5 1
1 5 4 1 2
4 4 3 2 2
4
5 3
2 3
2 5
4 1
Sample Output
4
3
-1
4
分析
对于地位最高这个条件可以离线处理,枚举队长是谁以处理询问
先将年龄离散化,那么这个队长可以选的区间就是\([a_x-k\sim a_x+k]\)
答案就是两人选择区间的交集大小,可以用树状数组+线段树实现
代码
#include <cstdio> #include <cctype> #include <algorithm> #include <vector> #define rr register using namespace std; const int N=100011; struct rec{int w,c,rk;}a[N]; int n,m,b[N],k,l[N],r[N],pos[N],ans[N],Rk[N],bas=1; vector<int>K[N]; inline signed min(int a,int b){return a<b?a:b;} inline signed max(int a,int b){return a>b?a:b;} struct zkw{ int w[N*3]; inline void build(int n){ for (;(bas<<=1)<n+2;); for (rr int i=1;i<=bas*2;++i) w[i]=-1; } inline void update(int x,int z){ x+=bas,w[x]=max(w[x],z); for (x>>=1;x;x>>=1) w[x]=max(w[x<<1],w[x<<1|1]); } inline signed query(int l,int r){ rr int ans=-1; for (l+=bas-1,r+=bas+1;l^r^1;l>>=1,r>>=1){ if (!(l&1)) ans=max(ans,w[l^1]); if (r&1) ans=max(ans,w[r^1]); } return ans; } }T; struct Tree_Array{ int c[N]; inline void update(int x,int y){ for (;x<=n;x+=-x&x) c[x]+=y; } inline signed query(int x){ rr int ans=0; for (;x;x-=-x&x) ans+=c[x]; return ans; } }C; inline signed iut(){ rr int ans=0; rr char c=getchar(); while (!isdigit(c)) c=getchar(); while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar(); return ans; } inline void print(int ans){ if (ans<0) putchar('-'),ans=-ans; if (ans>9) print(ans/10); putchar(ans%10+48); } bool cmp(rec x,rec y){return x.c>y.c;} signed main(){ n=iut(),k=iut(); for (rr int i=1;i<=n;++i) a[i].c=iut(),a[i].rk=i; for (rr int i=1;i<=n;++i) a[i].w=iut(),b[i]=a[i].w; sort(b+1,b+1+n),m=unique(b+1,b+1+n)-b-1,sort(a+1,a+1+n,cmp),T.build(m); for (rr int i=1;i<=n;++i){ l[i]=lower_bound(b+1,b+1+m,a[i].w-k)-b,r[i]=upper_bound(b+1,b+1+m,a[i].w+k)-b-1; Rk[a[i].rk]=i,C.update(a[i].w=lower_bound(b+1,b+1+m,a[i].w)-b,1); } rr int Test=iut(); for (rr int i=1;i<=Test;++i){ rr int x=Rk[iut()],y=Rk[iut()]; if (x<y) x^=y,y^=x,x^=y; K[y].push_back(i),pos[i]=x; } for (rr int i=1,p=1;i<=n;++i){ for (;p<=n&&a[p].c>=a[i].c;++p) T.update(a[p].w,C.query(r[p])-C.query(l[p]-1)); for (rr int j=0;j<K[i].size();++j){ rr int x=pos[K[i][j]],y=i; rr int L=max(l[x],l[y]),R=min(r[x],r[y]); if (L>R) ans[K[i][j]]=-1; else ans[K[i][j]]=T.query(L,R); } C.update(a[i].w,-1); } for (rr int i=1;i<=Test;++i) print(ans[i]),putchar(10); return 0; }
来源:https://www.cnblogs.com/Spare-No-Effort/p/12313110.html