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;
}
代码:link
标签:int,max,age,CF173E,三元组,ans,now 来源: https://www.cnblogs.com/blog-WHY/p/16365813.html