CF173E Camping Groups

\(\texttt{Description}\)

CodeForces 题目链接

洛谷题目链接

  • \(n\) 个人,第 \(i\) 个人地位 \(r_i\),年龄 \(a_i\)。要组队,队长满足以下条件:

    • 地位最大(可以并列)。

    • 与其组员年龄差距不超过 \(k\)

    \(q\) 个询问,第 \(i\) 个询问给出 \(x_i,y_i\),最大化 \(x_i,y_i\) 两个人在同一组里时组内的人数。

  • \(n,q\le 10^5\)\(k,a_i,r_i\le 10^9\)\(x_i,y_i\le n\)

\(\texttt{Solution}\)

对于每个询问,考虑求出符合条件的组长,再对组的大小取最大值。

因此先求出以每个人为组长时,组的最大人数 \(\text{size}_i\)。即对于第 \(i\) 个人,统计满足以下条件 \(j\) 的个数:

  • \(r_j\le r_i\)

  • \(a_i-k\le a_j\le a_i+k\)

可以考虑把所有人按照 \(a\) 从小到大排序,这样 \(a\) 满足单调性,可以用双指针维护第二个条件。同时用权值树状数组维护第一个条件。

再考虑对于每个询问,怎样的人可以作为组长。即对于第 \(i\) 个询问,组长 \(j\) 要满足 \(r_j\ge \max\{r_{x_i},r_{y_i}\}\)

那么先把所有询问按照 \(\max\{r_{x_i},r_{y_i}\}\) 从大到小排序,再把所有人按照 \(r\) 从大到小排序。

不妨设 \(a_{x_i}\le a_{y_i}\)(相反则交换)。要求的就是:

\[\max\limits_{a_{y_i}-k\le a_j\le a_{x_i}+k}\text{size}_j \]

权值线段树维护即可。两个权值数据结构都需要先离散化。如果你不想就动态开点吧。

时间复杂度为 \(\mathcal{O}((n+q)\log n)\),空间复杂度为 \(\mathcal{O}(n+q)\)

\(\texttt{Code}\)

Submission

$\texttt{Click For Code}$
#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
#include<bits/stdc++.h>
#define N 300005
#define ls x<<1
#define rs x<<1|1
using namespace std;
int n,k,Q,ta,tr,ans[N],sum[N],mx[N<<2],val[N],hs[N];
set<int>sa,sr;
map<int,int>mpa,mpr; 
struct person{
    int r,a,id;
}p[N];
struct question{
    int x,y,id;
}q[N];
void add(int x,int v){
    for(int i=x;i<=tr;i+=i&(-i)){
        sum[i]+=v;
    }
}
int qsum(int x){
    int ret=0;
    for(int i=x;i;i-=i&(-i)){
        ret+=sum[i];
    }
    return ret;
}
void modify(int x,int l,int r,int u,int v){
    if(l^r){
        int m=(l+r)>>1;
        if(u<=m){
            modify(ls,l,m,u,v);
        }else{
            modify(rs,m+1,r,u,v);
        }
        mx[x]=max(mx[ls],mx[rs]);
    }else{
        mx[x]=max(mx[x],v);
    }
}
int qmax(int x,int l,int r,int ql,int qr){
    if(ql<=l&&r<=qr){
        return mx[x];
    }
    int m=(l+r)>>1,ret=-1;
    if(ql<=m){
        ret=max(ret,qmax(ls,l,m,ql,qr));
    }
    if(qr>m){
        ret=max(ret,qmax(rs,m+1,r,ql,qr));
    }
    return ret;
}
int main(){
    memset(mx,-1,sizeof mx);
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;++i){
        scanf("%d",&p[i].r);
        sr.insert(p[i].r);
        p[i].id=i;
    }
    for(int i:sr){
        mpr[i]=++tr;
    }
    for(int i=1;i<=n;++i){
        scanf("%d",&p[i].a);
        sa.insert(p[i].a);
        sa.insert(p[i].a-k);
        sa.insert(p[i].a+k);
    }
    for(int i:sa){
        mpa[i]=++ta;
    }
    scanf("%d",&Q);
    for(int i=1;i<=Q;++i){
        scanf("%d%d",&q[i].x,&q[i].y);
        q[i].id=i;
    }
    sort(p+1,p+1+n,[](person i,person j){return i.a<j.a;});
    for(int i=1,l=0,r=0;i<=n;++i){
        for(;r<n&&p[r+1].a-p[i].a<=k;++r){
            add(mpr[p[r+1].r],1);
        }
        for(;l<r&&p[i].a-p[l+1].a>k;++l){
            add(mpr[p[l+1].r],-1);
        }
        val[p[i].id]=qsum(mpr[p[i].r]);
    }
    sort(p+1,p+1+n,[](person i,person j){return i.r>j.r;});
    for(int i=1;i<=n;++i){
        hs[p[i].id]=i;
    }
    sort(q+1,q+1+Q,[](question i,question j){return max(p[hs[i.x]].r,p[hs[i.y]].r)>max(p[hs[j.x]].r,p[hs[j.y]].r);});
    for(int i=1,j=0,x,y;i<=Q;++i){
        for(;j<n&&p[j+1].r>=max(p[hs[q[i].x]].r,p[hs[q[i].y]].r);++j){
            modify(1,1,ta,mpa[p[j+1].a],val[p[j+1].id]);
        }
        x=min(p[hs[q[i].x]].a,p[hs[q[i].y]].a);
        y=max(p[hs[q[i].x]].a,p[hs[q[i].y]].a);
        if(y-k>x+k){
            ans[q[i].id]=-1;
            continue;
        }
        ans[q[i].id]=qmax(1,1,ta,mpa[y-k],mpa[x+k]);
    }
    for(int i=1;i<=Q;++i){
        printf("%d\n",ans[i]);
    }
}
posted @ 2023-03-19 19:55  lzyqwq  阅读(21)  评论(0)    收藏  举报