由于题目描述过于沙雕,这里给出题目大意:
有nnn个人站在数轴的非负半轴上,其中一个是sg(自己理解),他站在0号点上。
对于其他的n−1n-1n−1个人,第iii个人用三元组(xi,yi,li)(x_i,y_i,l_i)(xi,yi,li)描述,说明这个人站在lil_ili点上,并有一个区间[xi,yi][x_i,y_i][xi,yi]来描述它的听觉范围。
题目给定一个LLL,第iii个人能把信息传到第jjj个人,满足li>ljl_i>l_jli>lj,li−lj<=Ll_i-l_j<=Lli−lj<=L且他们的听觉范围有交,传一次信息要1秒。sg的听觉范围是[0,inf][0,inf][0,inf]。询问每个人听到信息后把信息告诉sg要多少秒。
1≤n≤250000,0≤xi,yi,li≤2000000000,1≤L≤2000000000,xi≤yi1≤n≤250000,0≤x_i,y_i,l_i≤2000000000,1≤L≤2000000000,x_i≤y_i1≤n≤250000,0≤xi,yi,li≤2000000000,1≤L≤2000000000,xi≤yi
分析:
我们以lil_ili为关键字排序,lil_ili相同以编号排序。
因为只有右边的人可以传个左边的人,设f[i]f[i]f[i]表示左数第iii个人传到sg需要的时间。
我们可以用一个坐标(xi,yi)(x_i,y_i)(xi,yi)描述一个点,它的权值为f[i]f[i]f[i]。
对于f[j]f[j]f[j]的转移,需要把横坐标在[0,yj][0,y_j][0,yj],纵坐标在[xj,inf][x_j,inf][xj,inf]的点的权值取min。如果有一个点转移不到(距离超过LLL),把这个点权值改为infinfinf。
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
const int maxn=250007;
const int inf=2e9;
using namespace std;
int n,L,cnt,k,root;
int f[maxn],c[maxn*2],ans[maxn];
struct data{
int x,y,l,num;
}a[maxn];
struct rec{
int d[2];
};
bool operator ==(rec a,rec b)
{
return (a.d[0]==b.d[0]) && (a.d[1]==b.d[1]);
}
struct node{
int l,r,data;
}t[maxn*50];
bool cmp(data a,data b)
{
if (a.l==b.l) return a.num<b.num;
return a.l<b.l;
}
void change(int &p,rec l,rec r,rec a,int k,int op)
{
if (!p) p=++cnt;
if (l==r)
{
t[p].data=k;
return;
}
int mid=(l.d[op]+r.d[op])/2;
rec L=l,R=r;
L.d[op]=mid+1,R.d[op]=mid;
if (a.d[op]<=mid) change(t[p].l,l,R,a,k,op^1);
else change(t[p].r,L,r,a,k,op^1);
t[p].data=inf;
if (t[p].l) t[p].data=min(t[p].data,t[t[p].l].data);
if (t[p].r) t[p].data=min(t[p].data,t[t[p].r].data);
}
void getmin(int p,rec l,rec r,rec a,rec b,int op)
{
if (!p) return;
if (t[p].data>=k) return;
if ((l==a) && (r==b))
{
k=min(k,t[p].data);
return;
}
int mid=(l.d[op]+r.d[op])/2;
rec L=l,R=r;
L.d[op]=mid+1,R.d[op]=mid;
if (b.d[op]<=mid) getmin(t[p].l,l,R,a,b,op^1);
else if (a.d[op]>mid) getmin(t[p].r,L,r,a,b,op^1);
else
{
rec A=a,B=b;
A.d[op]=mid+1,B.d[op]=mid;
getmin(t[p].l,l,R,a,B,op^1);
getmin(t[p].r,L,r,A,b,op^1);
}
}
int main()
{
scanf("%d%d",&n,&L);
for (int i=1;i<n;i++)
{
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].l);
a[i].num=i;
}
a[n]=(data){0,inf,0};
for (int i=1;i<=n;i++)
{
c[i]=a[i].x,c[i+n]=a[i].y;
}
sort(c+1,c+n*2+1);
int size=unique(c+1,c+2*n+1)-c-1;
for (int i=1;i<=n;i++)
{
a[i].x=lower_bound(c+1,c+size+1,a[i].x)-c;
a[i].y=lower_bound(c+1,c+size+1,a[i].y)-c;
}
sort(a+1,a+n+1,cmp);
int j=1;
f[1]=0;
change(root,(rec){{1,1}},(rec){{size,size}},(rec){{a[1].x,a[1].y}},f[1],0);
for (int i=2;i<=n;i++)
{
while (a[i].l-a[j].l>L)
{
change(root,(rec){{1,1}},(rec){{size,size}},(rec){{a[j].x,a[j].y}},inf,0);
j++;
}
k=inf;
getmin(root,(rec){{1,1}},(rec){{size,size}},(rec){{1,a[i].x}},(rec){{a[i].y,size}},0);
f[i]=min(k+1,inf);
ans[a[i].num]=f[i];
change(root,(rec){{1,1}},(rec){{size,size}},(rec){{a[i].x,a[i].y}},f[i],0);
}
for (int i=1;i<n;i++)
{
if (ans[i]>=inf) printf("-1\n");
else printf("%d\n",ans[i]);
}
}