【JZOJ 3854】分组

来源:互联网 发布:淘宝新店引流量 编辑:程序博客网 时间:2024/06/15 12:14

Description

Bsny所在的精灵社区有n个居民,每个居民有一定的地位和年龄,ri表示第i个人的地位,ai表示第i个人的年龄。
最近社区里要举行活动,要求几个人分成一个小组,小组中必须要有一个队长,要成为队长有这样的条件:
1、队长在小组中的地位应该是最高的(可以并列第一);
2、小组中其他成员的年龄和队长的年龄差距不能超过K。
有些人想和自己亲密的人组在同一个小组,同时希望所在的小组人越多越好。比如x和y想在同一个小组,同时希望它们所在的小组人越多越好,当然,它们也必须选一个符合上述要求的队长,那么问你,要同时包含x和y的小组,最多可以组多少人?

Solution

先把每个人按地位排序,这样就可以预处理出每个人做组长可以领导多少人,(这里我用了树状数组)
再把输入的问题也按两个人中地位最大的排序,离线处理,
对于每个人可以确认一个年龄区间,要保证组长一定在这个年龄范围内,
用一个指针指向每一组人,按全部人的地位从大到小循环,看一下指向的组两人的最大地位是否大于当前的人,是则结算当前的人答案,指针后移,最后加上当前人的影响,(鄙人的语文辣鸡,大家可以看看代码理解一下)
这个可以用线段树,

复杂度:O(nlog(n))

Code

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fod(i,a,b) for(int i=a;i>=b;i--)#define NX(x) ((x)&(-(x)))using namespace std;const int N = 1e5+500;int read(int &n){    char ch=' ';int q=0,w=1;    for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());    if(ch=='-')w=-1,ch=getchar();    for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;}int n,m,m1;int zx[N],ans[N];struct qqww{    int rk,a,i,f,zx;}a[N];int A[N];int F[N];struct qwqw{    int x,y,i;}sc[N];int b[4*N];bool PX(qqww q,qqww w){return q.rk<w.rk || q.rk==w.rk&&q.a<w.a;}bool PPX(qwqw q,qwqw w){return a[q.x].rk<a[w.x].rk;}int SUM(int q){    int ans=0;    for(;q>0;q-=NX(q))ans+=F[q];    return ans;}void ADD(int q){for(;q<=m1;q+=NX(q))F[q]++;}int find(int l,int r,int e,int l1,int r1){    if(l==l1&&r==r1)return b[e];    int t=(l+r)>>1;    if(r1<=t)return find(l,t,e*2,l1,r1);        else if(t<l1)return find(t+1,r,e*2+1,l1,r1);            else return max(find(l,t,e*2,l1,t),find(t+1,r,e*2+1,t+1,r1));}void change(int l,int r,int e,int l1,int l2){    if(l==r){b[e]=max(b[e],l2);return;}    int t=(l+r)>>1;    if(l1<=t)change(l,t,e*2,l1,l2);        else change(t+1,r,e*2+1,l1,l2);    b[e]=max(b[e*2],b[e*2+1]);}int main(){    int q,w,_;    read(n),read(m);    fo(i,1,n)read(a[i].rk),a[i].i=i;    fo(i,1,n)A[i]=read(a[i].a);    sort(a+1,a+1+n,PX);    fo(i,1,n)zx[a[i].i]=i;    sort(A+1,A+1+n);    m1=1;    fo(i,2,n)if(A[i]!=A[i-1])A[++m1]=A[i];    int t=1;    fo(i,1,n)    {        a[i].zx=lower_bound(A+1,A+1+m1,a[i].a)-A;        ADD(a[i].zx);        if(a[i].rk!=a[i+1].rk)        while(t<=i)        {            q=lower_bound(A+1,A+1+m1,a[t].a-m)-A;            w=upper_bound(A+1,A+1+m1,a[t].a+m)-A-1;            a[t].f=SUM(w)-SUM(q-1),t++;        }    }    // fo(i,1,n)printf("%d ",a[i].f);printf("\n");    read(_);    int __=_;    fo(i,1,_)    {        read(q),read(w);q=zx[q],w=zx[w];        if(a[q].rk<a[w].rk)swap(q,w);        sc[i].x=q,sc[i].y=w;sc[i].i=i;    }    sort(sc+1,sc+1+_,PPX);    fod(i,n,0)    {        for(;a[i].rk<a[sc[_].x].rk;_--)        {            if(a[sc[_].x].a<a[sc[_].y].a)swap(sc[_].x,sc[_].y);            q=lower_bound(A+1,A+1+m1,a[sc[_].x].a-m)-A;q=max(1,q);            w=upper_bound(A+1,A+1+m1,a[sc[_].y].a+m)-A-1;            if(q<=w)ans[sc[_].i]=find(1,n,1,q,w);        }        change(1,n,1,a[i].zx,a[i].f);    }    fo(i,1,__)if(ans[i])printf("%d\n",ans[i]);else printf("-1\n");    return 0;}
0 0
原创粉丝点击