其他分享
首页 > 其他分享> > CF173E

CF173E

作者:互联网

独立想+写出来了,纪念一下。

思路:

离线线段树做法。

注意到,如果 \(i\) 成为了队长,他的队伍里必然包含了所有 \(r\leq r_i\) 且年龄差小于 \(k\) 的人,因为队员之间是没有限制的。

首先发现,对于一组 \(x\),\(y\) 的询问,对于任意 \(i\) 满足 \(r_i\geq\max(r_x,r_y)\) 且 \(a_i\) 在 \([a_x-k,a_x+k]\) 交 \([a_y-k,a_y+k]\) ,\(i\) 就可能成为队长,很显然,\(i\) 作为队长的队伍中必然包含了 \(x\) 和 \(y\)。

可以考虑求得任意 \(i\) 作为队长时队伍中的人数,转化为一个经典的二维偏序问题,按 \(r\) 排序后,动态开点值域线段树维护即可,记为 \(p_i\)。

sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++)
{
	add(root,1,2e9+10,a[i].age,1);
    if(i!=1&&a[i].res!=a[i-1].res)
    {
    	add(root,1,2e9+10,a[i].age,-1);
        while(lst<=i-1)
        {
        	p[lst]=sum(root,1,2e9+10,a[lst].age-k,a[lst].age+k);
            lst++;
		}
        add(root,1,2e9+10,a[i].age,1);
    }
}
while(lst<=n)
{
	p[lst]=sum(root,1,2e9+10,a[lst].age-k,a[lst].age+k);
    lst++;
}

随后问题转化就为了,就是给定了 \(n\) 个三元组,形如 \((r,a,p)\),求所有满足 \(r\geq k\) 且 \(a\) 属于 \([l,r]\) 的三元组的 \(p\) 的最大值,其中的 \(k\),\(l\),\(r\) 都是与询问的 \(x\),\(y\) 有关的,不多赘述。

这个问题显然可以按 \(k\) 排序,由于三元组已经按 \(r\) 排序,那么就消除了第一个限制,考虑在 \(a\) 处插入一个 \(p\) 然后取 \(\max\),动态开点值域线段树维护即可。

for(int i=1;i<=n;i++) 
{
    now[a[i].id]=i;
}
int q;cin>>q;
for(int i=1;i<=q;i++)
{
    int x,y;cin>>x>>y;
    x=now[x],y=now[y];
    Q[i]=(node1){x,y,max(a[x].res,a[y].res),i};
}
sort(Q+1,Q+1+q,cmp1);
int j=n;tot=0,root=0;
memset(t,0,sizeof(t));
for(int i=1;i<=q;i++)
{
    while(a[j].res>=Q[i].p&&j>0)
    {
        add1(root,1,2e9+10,a[j].age,p[j]);
        j--;
    }
    int x=Q[i].x,y=Q[i].y;
    int ans=-1;
    if(abs(a[x].age-a[y].age)<=k)
    {
        if(a[x].res==a[y].res)
        {
            ans=max(p[x],p[y]);
        }
        else if(a[x].res>a[y].res) ans=p[x];
        else ans=p[y];
    }
    int mi=min(a[x].age,a[y].age),mx=max(a[x].age,a[y].age);
    in now=get((in){max(0ll,mi-k),mi+k},(in){max(0ll,mx-k),mx+k});
    if(now.l!=-1)
    {
        ans=max(ans,query(root,1,2e9+10,now.l,now.r));
    }
    re[Q[i].id]=ans;
}

标签:int,max,age,CF173E,三元组,ans,now
来源: https://www.cnblogs.com/blog-WHY/p/16365813.html