由于题目描述过于沙雕,这里给出题目大意:
有
n
n
n个人站在数轴的非负半轴上,其中一个是sg(自己理解),他站在0号点上。
对于其他的
n
−
1
n-1
n−1个人,第
i
i
i个人用三元组
(
x
i
,
y
i
,
l
i
)
(x_i,y_i,l_i)
(xi,yi,li)描述,说明这个人站在
l
i
l_i
li点上,并有一个区间
[
x
i
,
y
i
]
[x_i,y_i]
[xi,yi]来描述它的听觉范围。
题目给定一个
L
L
L,第
i
i
i个人能把信息传到第
j
j
j个人,满足
l
i
>
l
j
l_i>l_j
li>lj,
l
i
−
l
j
<
=
L
l_i-l_j<=L
li−lj<=L且他们的听觉范围有交,传一次信息要1秒。sg的听觉范围是
[
0
,
i
n
f
]
[0,inf]
[0,inf]。询问每个人听到信息后把信息告诉sg要多少秒。
1
≤
n
≤
250000
,
0
≤
x
i
,
y
i
,
l
i
≤
2000000000
,
1
≤
L
≤
2000000000
,
x
i
≤
y
i
1≤n≤250000,0≤x_i,y_i,l_i≤2000000000,1≤L≤2000000000,x_i≤y_i
1≤n≤250000,0≤xi,yi,li≤2000000000,1≤L≤2000000000,xi≤yi
分析:
我们以
l
i
l_i
li为关键字排序,
l
i
l_i
li相同以编号排序。
因为只有右边的人可以传个左边的人,设
f
[
i
]
f[i]
f[i]表示左数第
i
i
i个人传到sg需要的时间。
我们可以用一个坐标
(
x
i
,
y
i
)
(x_i,y_i)
(xi,yi)描述一个点,它的权值为
f
[
i
]
f[i]
f[i]。
对于
f
[
j
]
f[j]
f[j]的转移,需要把横坐标在
[
0
,
y
j
]
[0,y_j]
[0,yj],纵坐标在
[
x
j
,
i
n
f
]
[x_j,inf]
[xj,inf]的点的权值取min。如果有一个点转移不到(距离超过
L
L
L),把这个点权值改为
i
n
f
inf
inf。
代码:
#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]);
}
}